1 /* 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 */ 16 package android.service.autofill; 17 18 import android.annotation.CallSuper; 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SdkConstant; 22 import android.app.Service; 23 import android.content.Intent; 24 import android.os.CancellationSignal; 25 import android.os.IBinder; 26 import android.os.ICancellationSignal; 27 import android.os.Looper; 28 import android.os.RemoteException; 29 import android.provider.Settings; 30 import android.util.Log; 31 import android.view.View; 32 import android.view.ViewStructure; 33 import android.view.autofill.AutofillId; 34 import android.view.autofill.AutofillManager; 35 import android.view.autofill.AutofillValue; 36 37 import com.android.internal.os.HandlerCaller; 38 import com.android.internal.os.SomeArgs; 39 40 /** 41 * An {@code AutofillService} is a service used to automatically fill the contents of the screen 42 * on behalf of a given user - for more information about autofill, read 43 * <a href="{@docRoot}preview/features/autofill.html">Autofill Framework</a>. 44 * 45 * <p>An {@code AutofillService} is only bound to the Android System for autofill purposes if: 46 * <ol> 47 * <li>It requires the {@code android.permission.BIND_AUTOFILL_SERVICE} permission in its 48 * manifest. 49 * <li>The user explicitly enables it using Android Settings (the 50 * {@link Settings#ACTION_REQUEST_SET_AUTOFILL_SERVICE} intent can be used to launch such 51 * Settings screen). 52 * </ol> 53 * 54 * <a name="BasicUsage"></a> 55 * <h3>Basic usage</h3> 56 * 57 * <p>The basic autofill process is defined by the workflow below: 58 * <ol> 59 * <li>User focus an editable {@link View}. 60 * <li>View calls {@link AutofillManager#notifyViewEntered(android.view.View)}. 61 * <li>A {@link ViewStructure} representing all views in the screen is created. 62 * <li>The Android System binds to the service and calls {@link #onConnected()}. 63 * <li>The service receives the view structure through the 64 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)}. 65 * <li>The service replies through {@link FillCallback#onSuccess(FillResponse)}. 66 * <li>The Android System calls {@link #onDisconnected()} and unbinds from the 67 * {@code AutofillService}. 68 * <li>The Android System displays an UI affordance with the options sent by the service. 69 * <li>The user picks an option. 70 * <li>The proper views are autofilled. 71 * </ol> 72 * 73 * <p>This workflow was designed to minimize the time the Android System is bound to the service; 74 * for each call, it: binds to service, waits for the reply, and unbinds right away. Furthermore, 75 * those calls are considered stateless: if the service needs to keep state between calls, it must 76 * do its own state management (keeping in mind that the service's process might be killed by the 77 * Android System when unbound; for example, if the device is running low in memory). 78 * 79 * <p>Typically, the 80 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} will: 81 * <ol> 82 * <li>Parse the view structure looking for autofillable views (for example, using 83 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillHints()}. 84 * <li>Match the autofillable views with the user's data. 85 * <li>Create a {@link Dataset} for each set of user's data that match those fields. 86 * <li>Fill the dataset(s) with the proper {@link AutofillId}s and {@link AutofillValue}s. 87 * <li>Add the dataset(s) to the {@link FillResponse} passed to 88 * {@link FillCallback#onSuccess(FillResponse)}. 89 * </ol> 90 * 91 * <p>For example, for a login screen with username and password views where the user only has one 92 * account in the service, the response could be: 93 * 94 * <pre class="prettyprint"> 95 * new FillResponse.Builder() 96 * .addDataset(new Dataset.Builder() 97 * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) 98 * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) 99 * .build()) 100 * .build(); 101 * </pre> 102 * 103 * <p>But if the user had 2 accounts instead, the response could be: 104 * 105 * <pre class="prettyprint"> 106 * new FillResponse.Builder() 107 * .addDataset(new Dataset.Builder() 108 * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) 109 * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) 110 * .build()) 111 * .addDataset(new Dataset.Builder() 112 * .setValue(id1, AutofillValue.forText("flanders"), createPresentation("flanders")) 113 * .setValue(id2, AutofillValue.forText("OkelyDokelyDo"), createPresentation("password for flanders")) 114 * .build()) 115 * .build(); 116 * </pre> 117 * 118 * <p>If the service does not find any autofillable view in the view structure, it should pass 119 * {@code null} to {@link FillCallback#onSuccess(FillResponse)}; if the service encountered an error 120 * processing the request, it should call {@link FillCallback#onFailure(CharSequence)}. For 121 * performance reasons, it's paramount that the service calls either 122 * {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)} for 123 * each {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} received - if it 124 * doesn't, the request will eventually time out and be discarded by the Android System. 125 * 126 * <a name="SavingUserData"></a> 127 * <h3>Saving user data</h3> 128 * 129 * <p>If the service is also interested on saving the data filled by the user, it must set a 130 * {@link SaveInfo} object in the {@link FillResponse}. See {@link SaveInfo} for more details and 131 * examples. 132 * 133 * <a name="UserAuthentication"></a> 134 * <h3>User authentication</h3> 135 * 136 * <p>The service can provide an extra degree of security by requiring the user to authenticate 137 * before an app can be autofilled. The authentication is typically required in 2 scenarios: 138 * <ul> 139 * <li>To unlock the user data (for example, using a master password or fingerprint 140 * authentication) - see 141 * {@link FillResponse.Builder#setAuthentication(AutofillId[], android.content.IntentSender, android.widget.RemoteViews)}. 142 * <li>To unlock a specific dataset (for example, by providing a CVC for a credit card) - see 143 * {@link Dataset.Builder#setAuthentication(android.content.IntentSender)}. 144 * </ul> 145 * 146 * <p>When using authentication, it is recommended to encrypt only the sensitive data and leave 147 * labels unencrypted, so they can be used on presentation views. For example, if the user has a 148 * home and a work address, the {@code Home} and {@code Work} labels should be stored unencrypted 149 * (since they don't have any sensitive data) while the address data per se could be stored in an 150 * encrypted storage. Then when the user chooses the {@code Home} dataset, the platform starts 151 * the authentication flow, and the service can decrypt the sensitive data. 152 * 153 * <p>The authentication mechanism can also be used in scenarios where the service needs multiple 154 * steps to determine the datasets that can fill a screen. For example, when autofilling a financial 155 * app where the user has accounts for multiple banks, the workflow could be: 156 * 157 * <ol> 158 * <li>The first {@link FillResponse} contains datasets with the credentials for the financial 159 * app, plus a "fake" dataset whose presentation says "Tap here for banking apps credentials". 160 * <li>When the user selects the fake dataset, the service displays a dialog with available 161 * banking apps. 162 * <li>When the user select a banking app, the service replies with a new {@link FillResponse} 163 * containing the datasets for that bank. 164 * </ol> 165 * 166 * <p>Another example of multiple-steps dataset selection is when the service stores the user 167 * credentials in "vaults": the first response would contain fake datasets with the vault names, 168 * and the subsequent response would contain the app credentials stored in that vault. 169 * 170 * <a name="DataPartioning"></a> 171 * <h3>Data partitioning</h3> 172 * 173 * <p>The autofillable views in a screen should be grouped in logical groups called "partitions". 174 * Typical partitions are: 175 * <ul> 176 * <li>Credentials (username/email address, password). 177 * <li>Address (street, city, state, zip code, etc). 178 * <li>Payment info (credit card number, expiration date, and verification code). 179 * </ul> 180 * <p>For security reasons, when a screen has more than one partition, it's paramount that the 181 * contents of a dataset do not spawn multiple partitions, specially when one of the partitions 182 * contains data that is not specific to the application being autofilled. For example, a dataset 183 * should not contain fields for username, password, and credit card information. The reason for 184 * this rule is that a malicious app could draft a view structure where the credit card fields 185 * are not visible, so when the user selects a dataset from the username UI, the credit card info is 186 * released to the application without the user knowledge. Similarly, it's recommended to always 187 * protect a dataset that contains sensitive information by requiring dataset authentication 188 * (see {@link Dataset.Builder#setAuthentication(android.content.IntentSender)}), and to include 189 * info about the "primary" field of the partition in the custom presentation for "secondary" 190 * fields — that would prevent a malicious app from getting the "primary" fields without the 191 * user realizing they're being released (for example, a malicious app could have fields for a 192 * credit card number, verification code, and expiration date crafted in a way that just the latter 193 * is visible; by explicitly indicating the expiration date is related to a given credit card 194 * number, the service would be providing a visual clue for the users to check what would be 195 * released upon selecting that field). 196 * 197 * <p>When the service detects that a screen has multiple partitions, it should return a 198 * {@link FillResponse} with just the datasets for the partition that originated the request (i.e., 199 * the partition that has the {@link android.app.assist.AssistStructure.ViewNode} whose 200 * {@link android.app.assist.AssistStructure.ViewNode#isFocused()} returns {@code true}); then if 201 * the user selects a field from a different partition, the Android System will make another 202 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} call for that partition, 203 * and so on. 204 * 205 * <p>Notice that when the user autofill a partition with the data provided by the service and the 206 * user did not change these fields, the autofilled value is sent back to the service in the 207 * subsequent calls (and can be obtained by calling 208 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}). This is useful in the 209 * cases where the service must create datasets for a partition based on the choice made in a 210 * previous partition. For example, the 1st response for a screen that have credentials and address 211 * partitions could be: 212 * 213 * <pre class="prettyprint"> 214 * new FillResponse.Builder() 215 * .addDataset(new Dataset.Builder() // partition 1 (credentials) 216 * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) 217 * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) 218 * .build()) 219 * .addDataset(new Dataset.Builder() // partition 1 (credentials) 220 * .setValue(id1, AutofillValue.forText("flanders"), createPresentation("flanders")) 221 * .setValue(id2, AutofillValue.forText("OkelyDokelyDo"), createPresentation("password for flanders")) 222 * .build()) 223 * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD, 224 * new AutofillId[] { id1, id2 }) 225 * .build()) 226 * .build(); 227 * </pre> 228 * 229 * <p>Then if the user selected {@code flanders}, the service would get a new 230 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} call, with the values of 231 * the fields {@code id1} and {@code id2} prepopulated, so the service could then fetch the address 232 * for the Flanders account and return the following {@link FillResponse} for the address partition: 233 * 234 * <pre class="prettyprint"> 235 * new FillResponse.Builder() 236 * .addDataset(new Dataset.Builder() // partition 2 (address) 237 * .setValue(id3, AutofillValue.forText("744 Evergreen Terrace"), createPresentation("744 Evergreen Terrace")) // street 238 * .setValue(id4, AutofillValue.forText("Springfield"), createPresentation("Springfield")) // city 239 * .build()) 240 * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD | SaveInfo.SAVE_DATA_TYPE_ADDRESS, 241 * new AutofillId[] { id1, id2 }) // username and password 242 * .setOptionalIds(new AutofillId[] { id3, id4 }) // state and zipcode 243 * .build()) 244 * .build(); 245 * </pre> 246 * 247 * <p>When the service returns multiple {@link FillResponse}, the last one overrides the previous; 248 * that's why the {@link SaveInfo} in the 2nd request above has the info for both partitions. 249 * 250 * <a name="PackageVerification"></a> 251 * <h3>Package verification</h3> 252 * 253 * <p>When autofilling app-specific data (like username and password), the service must verify 254 * the authenticity of the request by obtaining all signing certificates of the app being 255 * autofilled, and only fulfilling the request when they match the values that were 256 * obtained when the data was first saved — such verification is necessary to avoid phishing 257 * attempts by apps that were sideloaded in the device with the same package name of another app. 258 * Here's an example on how to achieve that by hashing the signing certificates: 259 * 260 * <pre class="prettyprint"> 261 * private String getCertificatesHash(String packageName) throws Exception { 262 * PackageManager pm = mContext.getPackageManager(); 263 * PackageInfo info = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 264 * ArrayList<String> hashes = new ArrayList<>(info.signatures.length); 265 * for (Signature sig : info.signatures) { 266 * byte[] cert = sig.toByteArray(); 267 * MessageDigest md = MessageDigest.getInstance("SHA-256"); 268 * md.update(cert); 269 * hashes.add(toHexString(md.digest())); 270 * } 271 * Collections.sort(hashes); 272 * StringBuilder hash = new StringBuilder(); 273 * for (int i = 0; i < hashes.size(); i++) { 274 * hash.append(hashes.get(i)); 275 * } 276 * return hash.toString(); 277 * } 278 * </pre> 279 * 280 * <p>If the service did not store the signing certificates data the first time the data was saved 281 * — for example, because the data was created by a previous version of the app that did not 282 * use the Autofill Framework — the service should warn the user that the authenticity of the 283 * app cannot be confirmed (see an example on how to show such warning in the 284 * <a href="#WebSecurityDisclaimer">Web security</a> section below), and if the user agrees, 285 * then the service could save the data from the signing ceriticates for future use. 286 * 287 * <a name="IgnoringViews"></a> 288 * <h3>Ignoring views</h3> 289 * 290 * <p>If the service find views that cannot be autofilled (for example, a text field representing 291 * the response to a Captcha challenge), it should mark those views as ignored by 292 * calling {@link FillResponse.Builder#setIgnoredIds(AutofillId...)} so the system does not trigger 293 * a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are 294 * focused. 295 * 296 * <a name="WebSecurity"></a> 297 * <h3>Web security</h3> 298 * 299 * <p>When handling autofill requests that represent web pages (typically 300 * view structures whose root's {@link android.app.assist.AssistStructure.ViewNode#getClassName()} 301 * is a {@link android.webkit.WebView}), the service should take the following steps to verify if 302 * the structure can be autofilled with the data associated with the app requesting it: 303 * 304 * <ol> 305 * <li>Use the {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()} to get the 306 * source of the document. 307 * <li>Get the canonical domain using the 308 * <a href="https://publicsuffix.org/">Public Suffix List</a> (see example below). 309 * <li>Use <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a> 310 * to obtain the package name and certificate fingerprint of the package corresponding to 311 * the canonical domain. 312 * <li>Make sure the certificate fingerprint matches the value returned by Package Manager 313 * (see "Package verification" section above). 314 * </ol> 315 * 316 * <p>Here's an example on how to get the canonical domain using 317 * <a href="https://github.com/google/guava">Guava</a>: 318 * 319 * <pre class="prettyprint"> 320 * private static String getCanonicalDomain(String domain) { 321 * InternetDomainName idn = InternetDomainName.from(domain); 322 * while (idn != null && !idn.isTopPrivateDomain()) { 323 * idn = idn.parent(); 324 * } 325 * return idn == null ? null : idn.toString(); 326 * } 327 * </pre> 328 * 329 * <a name="WebSecurityDisclaimer"></a> 330 * <p>If the association between the web domain and app package cannot be verified through the steps 331 * above, but the service thinks that it is appropriate to fill persisted credentials that are 332 * stored for the web domain, the service should warn the user about the potential data 333 * leakage first, and ask for the user to confirm. For example, the service could: 334 * 335 * <ol> 336 * <li>Create a dataset that requires 337 * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authentication} to 338 * unlock. 339 * <li>Include the web domain in the custom presentation for the 340 * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, android.widget.RemoteViews) 341 * dataset value}. 342 * <li>When the user selects that dataset, show a disclaimer dialog explaining that the app is 343 * requesting credentials for a web domain, but the service could not verify if the app owns 344 * that domain. If the user agrees, then the service can unlock the dataset. 345 * <li>Similarly, when adding a {@link SaveInfo} object for the request, the service should 346 * include the above disclaimer in the {@link SaveInfo.Builder#setDescription(CharSequence)}. 347 * </ol> 348 * 349 * <p>This same procedure could also be used when the autofillable data is contained inside an 350 * {@code IFRAME}, in which case the WebView generates a new autofill context when a node inside 351 * the {@code IFRAME} is focused, with the root node containing the {@code IFRAME}'s {@code src} 352 * attribute on {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()}. A typical and 353 * legitimate use case for this scenario is a financial app that allows the user 354 * to login on different bank accounts. For example, a financial app {@code my_financial_app} could 355 * use a WebView that loads contents from {@code banklogin.my_financial_app.com}, which contains an 356 * {@code IFRAME} node whose {@code src} attribute is {@code login.some_bank.com}. When fulfilling 357 * that request, the service could add an 358 * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authenticated dataset} 359 * whose presentation displays "Username for some_bank.com" and 360 * "Password for some_bank.com". Then when the user taps one of these options, the service 361 * shows the disclaimer dialog explaining that selecting that option would release the 362 * {@code login.some_bank.com} credentials to the {@code my_financial_app}; if the user agrees, 363 * then the service returns an unlocked dataset with the {@code some_bank.com} credentials. 364 * 365 * <p><b>Note:</b> The autofill service could also whitelist well-known browser apps and skip the 366 * verifications above, as long as the service can verify the authenticity of the browser app by 367 * checking its signing certificate. 368 * 369 * <a name="MultipleStepsSave"></a> 370 * <h3>Saving when data is split in multiple screens</h3> 371 * 372 * Apps often split the user data in multiple screens in the same activity, specially in 373 * activities used to create a new user account. For example, the first screen asks for a username, 374 * and if the username is available, it moves to a second screen, which asks for a password. 375 * 376 * <p>It's tricky to handle save for autofill in these situations, because the autofill service must 377 * wait until the user enters both fields before the autofill save UI can be shown. But it can be 378 * done by following the steps below: 379 * 380 * <ol> 381 * <li>In the first 382 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback) fill request}, the service 383 * adds a {@link FillResponse.Builder#setClientState(android.os.Bundle) client state bundle} in 384 * the response, containing the autofill ids of the partial fields present in the screen. 385 * <li>In the second 386 * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback) fill request}, the service 387 * retrieves the {@link FillRequest#getClientState() client state bundle}, gets the autofill ids 388 * set in the previous request from the client state, and adds these ids and the 389 * {@link SaveInfo#FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} to the {@link SaveInfo} used in the second 390 * response. 391 * <li>In the {@link #onSaveRequest(SaveRequest, SaveCallback) save request}, the service uses the 392 * proper {@link FillContext fill contexts} to get the value of each field (there is one fill 393 * context per fill request). 394 * </ol> 395 * 396 * <p>For example, in an app that uses 2 steps for the username and password fields, the workflow 397 * would be: 398 * <pre class="prettyprint"> 399 * // On first fill request 400 * AutofillId usernameId = // parse from AssistStructure; 401 * Bundle clientState = new Bundle(); 402 * clientState.putParcelable("usernameId", usernameId); 403 * fillCallback.onSuccess( 404 * new FillResponse.Builder() 405 * .setClientState(clientState) 406 * .setSaveInfo(new SaveInfo 407 * .Builder(SaveInfo.SAVE_DATA_TYPE_USERNAME, new AutofillId[] {usernameId}) 408 * .build()) 409 * .build()); 410 * 411 * // On second fill request 412 * Bundle clientState = fillRequest.getClientState(); 413 * AutofillId usernameId = clientState.getParcelable("usernameId"); 414 * AutofillId passwordId = // parse from AssistStructure 415 * clientState.putParcelable("passwordId", passwordId); 416 * fillCallback.onSuccess( 417 * new FillResponse.Builder() 418 * .setClientState(clientState) 419 * .setSaveInfo(new SaveInfo 420 * .Builder(SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD, 421 * new AutofillId[] {usernameId, passwordId}) 422 * .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) 423 * .build()) 424 * .build()); 425 * 426 * // On save request 427 * Bundle clientState = saveRequest.getClientState(); 428 * AutofillId usernameId = clientState.getParcelable("usernameId"); 429 * AutofillId passwordId = clientState.getParcelable("passwordId"); 430 * List<FillContext> fillContexts = saveRequest.getFillContexts(); 431 * 432 * FillContext usernameContext = fillContexts.get(0); 433 * ViewNode usernameNode = findNodeByAutofillId(usernameContext.getStructure(), usernameId); 434 * AutofillValue username = usernameNode.getAutofillValue().getTextValue().toString(); 435 * 436 * FillContext passwordContext = fillContexts.get(1); 437 * ViewNode passwordNode = findNodeByAutofillId(passwordContext.getStructure(), passwordId); 438 * AutofillValue password = passwordNode.getAutofillValue().getTextValue().toString(); 439 * 440 * save(username, password); 441 * 442 * </pre> 443 */ 444 public abstract class AutofillService extends Service { 445 private static final String TAG = "AutofillService"; 446 447 /** 448 * The {@link Intent} that must be declared as handled by the service. 449 * To be supported, the service must also require the 450 * {@link android.Manifest.permission#BIND_AUTOFILL_SERVICE} permission so 451 * that other applications can not abuse it. 452 */ 453 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 454 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; 455 456 /** 457 * Name under which a AutoFillService component publishes information about itself. 458 * This meta-data should reference an XML resource containing a 459 * <code><{@link 460 * android.R.styleable#AutofillService autofill-service}></code> tag. 461 * This is a a sample XML file configuring an AutoFillService: 462 * <pre> <autofill-service 463 * android:settingsActivity="foo.bar.SettingsActivity" 464 * . . . 465 * /></pre> 466 */ 467 public static final String SERVICE_META_DATA = "android.autofill"; 468 469 // Handler messages. 470 private static final int MSG_CONNECT = 1; 471 private static final int MSG_DISCONNECT = 2; 472 private static final int MSG_ON_FILL_REQUEST = 3; 473 private static final int MSG_ON_SAVE_REQUEST = 4; 474 475 private final IAutoFillService mInterface = new IAutoFillService.Stub() { 476 @Override 477 public void onConnectedStateChanged(boolean connected) { 478 if (connected) { 479 mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget(); 480 } else { 481 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget(); 482 } 483 } 484 485 @Override 486 public void onFillRequest(FillRequest request, IFillCallback callback) { 487 ICancellationSignal transport = CancellationSignal.createTransport(); 488 try { 489 callback.onCancellable(transport); 490 } catch (RemoteException e) { 491 e.rethrowFromSystemServer(); 492 } 493 mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request, 494 CancellationSignal.fromTransport(transport), callback) 495 .sendToTarget(); 496 } 497 498 @Override 499 public void onSaveRequest(SaveRequest request, ISaveCallback callback) { 500 mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request, 501 callback).sendToTarget(); 502 } 503 }; 504 505 private final HandlerCaller.Callback mHandlerCallback = (msg) -> { 506 switch (msg.what) { 507 case MSG_CONNECT: { 508 onConnected(); 509 break; 510 } case MSG_ON_FILL_REQUEST: { 511 final SomeArgs args = (SomeArgs) msg.obj; 512 final FillRequest request = (FillRequest) args.arg1; 513 final CancellationSignal cancellation = (CancellationSignal) args.arg2; 514 final IFillCallback callback = (IFillCallback) args.arg3; 515 final FillCallback fillCallback = new FillCallback(callback, request.getId()); 516 args.recycle(); 517 onFillRequest(request, cancellation, fillCallback); 518 break; 519 } case MSG_ON_SAVE_REQUEST: { 520 final SomeArgs args = (SomeArgs) msg.obj; 521 final SaveRequest request = (SaveRequest) args.arg1; 522 final ISaveCallback callback = (ISaveCallback) args.arg2; 523 final SaveCallback saveCallback = new SaveCallback(callback); 524 args.recycle(); 525 onSaveRequest(request, saveCallback); 526 break; 527 } case MSG_DISCONNECT: { 528 onDisconnected(); 529 break; 530 } default: { 531 Log.w(TAG, "MyCallbacks received invalid message type: " + msg); 532 } 533 } 534 }; 535 536 private HandlerCaller mHandlerCaller; 537 538 @CallSuper 539 @Override 540 public void onCreate() { 541 super.onCreate(); 542 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true); 543 } 544 545 @Override 546 public final IBinder onBind(Intent intent) { 547 if (SERVICE_INTERFACE.equals(intent.getAction())) { 548 return mInterface.asBinder(); 549 } 550 Log.w(TAG, "Tried to bind to wrong intent: " + intent); 551 return null; 552 } 553 554 /** 555 * Called when the Android system connects to service. 556 * 557 * <p>You should generally do initialization here rather than in {@link #onCreate}. 558 */ 559 public void onConnected() { 560 } 561 562 /** 563 * Called by the Android system do decide if a screen can be autofilled by the service. 564 * 565 * <p>Service must call one of the {@link FillCallback} methods (like 566 * {@link FillCallback#onSuccess(FillResponse)} 567 * or {@link FillCallback#onFailure(CharSequence)}) 568 * to notify the result of the request. 569 * 570 * @param request the {@link FillRequest request} to handle. 571 * See {@link FillResponse} for examples of multiple-sections requests. 572 * @param cancellationSignal signal for observing cancellation requests. The system will use 573 * this to notify you that the fill result is no longer needed and you should stop 574 * handling this fill request in order to save resources. 575 * @param callback object used to notify the result of the request. 576 */ 577 public abstract void onFillRequest(@NonNull FillRequest request, 578 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); 579 580 /** 581 * Called when the user requests the service to save the contents of a screen. 582 * 583 * <p>Service must call one of the {@link SaveCallback} methods (like 584 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) 585 * to notify the Android System of the result of the request. 586 * 587 * <p>If the service could not handle the request right away—for example, because it must 588 * launch an activity asking the user to authenticate first or because the network is 589 * down—the service could keep the {@link SaveRequest request} and reuse it later, 590 * but the service must call {@link SaveCallback#onSuccess()} right away. 591 * 592 * <p><b>Note:</b> To retrieve the actual value of fields input by the user, the service 593 * should call 594 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls 595 * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no 596 * guarantee such method will return the most recent value of the field. 597 * 598 * @param request the {@link SaveRequest request} to handle. 599 * See {@link FillResponse} for examples of multiple-sections requests. 600 * @param callback object used to notify the result of the request. 601 */ 602 public abstract void onSaveRequest(@NonNull SaveRequest request, 603 @NonNull SaveCallback callback); 604 605 /** 606 * Called when the Android system disconnects from the service. 607 * 608 * <p> At this point this service may no longer be an active {@link AutofillService}. 609 */ 610 public void onDisconnected() { 611 } 612 613 /** 614 * Gets the events that happened after the last 615 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)} 616 * call. 617 * 618 * <p>This method is typically used to keep track of previous user actions to optimize further 619 * requests. For example, the service might return email addresses in alphabetical order by 620 * default, but change that order based on the address the user picked on previous requests. 621 * 622 * <p>The history is not persisted over reboots, and it's cleared every time the service 623 * replies to a {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} by calling 624 * {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)} 625 * (if the service doesn't call any of these methods, the history will clear out after some 626 * pre-defined time). Hence, the service should call {@link #getFillEventHistory()} before 627 * finishing the {@link FillCallback}. 628 * 629 * @return The history or {@code null} if there are no events. 630 */ 631 @Nullable public final FillEventHistory getFillEventHistory() { 632 final AutofillManager afm = getSystemService(AutofillManager.class); 633 634 if (afm == null) { 635 return null; 636 } else { 637 return afm.getFillEventHistory(); 638 } 639 } 640 } 641