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 17 package com.android.server.autofill; 18 19 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; 20 21 import static com.android.server.autofill.Helper.sDebug; 22 import static com.android.server.autofill.Helper.sVerbose; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.IntentSender; 29 import android.os.IBinder; 30 import android.os.ICancellationSignal; 31 import android.os.RemoteException; 32 import android.service.autofill.AutofillService; 33 import android.service.autofill.FillRequest; 34 import android.service.autofill.FillResponse; 35 import android.service.autofill.IAutoFillService; 36 import android.service.autofill.IFillCallback; 37 import android.service.autofill.ISaveCallback; 38 import android.service.autofill.SaveRequest; 39 import android.text.format.DateUtils; 40 import android.util.Slog; 41 42 import com.android.internal.infra.AbstractSinglePendingRequestRemoteService; 43 44 import java.util.concurrent.CompletableFuture; 45 46 final class RemoteFillService 47 extends AbstractSinglePendingRequestRemoteService<RemoteFillService, IAutoFillService> { 48 49 private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; 50 private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; 51 52 private final FillServiceCallbacks mCallbacks; 53 54 public interface FillServiceCallbacks extends VultureCallback<RemoteFillService> { onFillRequestSuccess(int requestId, @Nullable FillResponse response, @NonNull String servicePackageName, int requestFlags)55 void onFillRequestSuccess(int requestId, @Nullable FillResponse response, 56 @NonNull String servicePackageName, int requestFlags); onFillRequestFailure(int requestId, @Nullable CharSequence message)57 void onFillRequestFailure(int requestId, @Nullable CharSequence message); onFillRequestTimeout(int requestId)58 void onFillRequestTimeout(int requestId); onSaveRequestSuccess(@onNull String servicePackageName, @Nullable IntentSender intentSender)59 void onSaveRequestSuccess(@NonNull String servicePackageName, 60 @Nullable IntentSender intentSender); 61 // TODO(b/80093094): add timeout here too? onSaveRequestFailure(@ullable CharSequence message, @NonNull String servicePackageName)62 void onSaveRequestFailure(@Nullable CharSequence message, 63 @NonNull String servicePackageName); 64 } 65 RemoteFillService(Context context, ComponentName componentName, int userId, FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed)66 RemoteFillService(Context context, ComponentName componentName, int userId, 67 FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { 68 super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks, 69 context.getMainThreadHandler(), Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS 70 | (bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0), sVerbose); 71 mCallbacks = callbacks; 72 } 73 74 @Override // from AbstractRemoteService handleOnConnectedStateChanged(boolean state)75 protected void handleOnConnectedStateChanged(boolean state) { 76 if (mService == null) { 77 Slog.w(mTag, "onConnectedStateChanged(): null service"); 78 return; 79 } 80 try { 81 mService.onConnectedStateChanged(state); 82 } catch (Exception e) { 83 Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e); 84 } 85 } 86 87 @Override // from AbstractRemoteService getServiceInterface(IBinder service)88 protected IAutoFillService getServiceInterface(IBinder service) { 89 return IAutoFillService.Stub.asInterface(service); 90 } 91 92 @Override // from AbstractRemoteService getTimeoutIdleBindMillis()93 protected long getTimeoutIdleBindMillis() { 94 return TIMEOUT_IDLE_BIND_MILLIS; 95 } 96 97 @Override // from AbstractRemoteService getRemoteRequestMillis()98 protected long getRemoteRequestMillis() { 99 return TIMEOUT_REMOTE_REQUEST_MILLIS; 100 } 101 102 /** 103 * Cancel the currently pending request. 104 * 105 * <p>This can be used when the request is unnecessary or will be superceeded by a request that 106 * will soon be queued. 107 * 108 * @return the future id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if 109 * no {@link PendingFillRequest} was canceled. 110 */ cancelCurrentRequest()111 public CompletableFuture<Integer> cancelCurrentRequest() { 112 return CompletableFuture.supplyAsync(() -> { 113 if (isDestroyed()) { 114 return INVALID_REQUEST_ID; 115 } 116 117 BasePendingRequest<RemoteFillService, IAutoFillService> canceledRequest = 118 handleCancelPendingRequest(); 119 return canceledRequest instanceof PendingFillRequest 120 ? ((PendingFillRequest) canceledRequest).mRequest.getId() 121 : INVALID_REQUEST_ID; 122 }, mHandler::post); 123 } 124 125 public void onFillRequest(@NonNull FillRequest request) { 126 scheduleRequest(new PendingFillRequest(request, this)); 127 } 128 129 public void onSaveRequest(@NonNull SaveRequest request) { 130 scheduleRequest(new PendingSaveRequest(request, this)); 131 } 132 133 private boolean handleResponseCallbackCommon( 134 @NonNull PendingRequest<RemoteFillService, IAutoFillService> pendingRequest) { 135 if (isDestroyed()) return false; 136 137 if (mPendingRequest == pendingRequest) { 138 mPendingRequest = null; 139 } 140 return true; 141 } 142 143 private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, 144 @Nullable FillResponse response, int requestFlags) { 145 mHandler.post(() -> { 146 if (handleResponseCallbackCommon(pendingRequest)) { 147 mCallbacks.onFillRequestSuccess(pendingRequest.mRequest.getId(), response, 148 mComponentName.getPackageName(), requestFlags); 149 } 150 }); 151 } 152 153 private void dispatchOnFillRequestFailure(@NonNull PendingFillRequest pendingRequest, 154 @Nullable CharSequence message) { 155 mHandler.post(() -> { 156 if (handleResponseCallbackCommon(pendingRequest)) { 157 mCallbacks.onFillRequestFailure(pendingRequest.mRequest.getId(), message); 158 } 159 }); 160 } 161 162 private void dispatchOnFillRequestTimeout(@NonNull PendingFillRequest pendingRequest) { 163 mHandler.post(() -> { 164 if (handleResponseCallbackCommon(pendingRequest)) { 165 mCallbacks.onFillRequestTimeout(pendingRequest.mRequest.getId()); 166 } 167 }); 168 } 169 170 private void dispatchOnFillTimeout(@NonNull ICancellationSignal cancellationSignal) { 171 mHandler.post(() -> { 172 try { 173 cancellationSignal.cancel(); 174 } catch (RemoteException e) { 175 Slog.w(mTag, "Error calling cancellation signal: " + e); 176 } 177 }); 178 } 179 180 private void dispatchOnSaveRequestSuccess(PendingSaveRequest pendingRequest, 181 IntentSender intentSender) { 182 mHandler.post(() -> { 183 if (handleResponseCallbackCommon(pendingRequest)) { 184 mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName(), intentSender); 185 } 186 }); 187 } 188 189 private void dispatchOnSaveRequestFailure(PendingSaveRequest pendingRequest, 190 @Nullable CharSequence message) { 191 mHandler.post(() -> { 192 if (handleResponseCallbackCommon(pendingRequest)) { 193 mCallbacks.onSaveRequestFailure(message, mComponentName.getPackageName()); 194 } 195 }); 196 } 197 198 private static final class PendingFillRequest 199 extends PendingRequest<RemoteFillService, IAutoFillService> { 200 private final FillRequest mRequest; 201 private final IFillCallback mCallback; 202 private ICancellationSignal mCancellation; 203 204 public PendingFillRequest(FillRequest request, RemoteFillService service) { 205 super(service); 206 mRequest = request; 207 208 mCallback = new IFillCallback.Stub() { 209 @Override 210 public void onCancellable(ICancellationSignal cancellation) { 211 synchronized (mLock) { 212 final boolean cancelled; 213 synchronized (mLock) { 214 mCancellation = cancellation; 215 cancelled = isCancelledLocked(); 216 } 217 if (cancelled) { 218 try { 219 cancellation.cancel(); 220 } catch (RemoteException e) { 221 Slog.e(mTag, "Error requesting a cancellation", e); 222 } 223 } 224 } 225 } 226 227 @Override 228 public void onSuccess(FillResponse response) { 229 if (!finish()) return; 230 231 final RemoteFillService remoteService = getService(); 232 if (remoteService != null) { 233 remoteService.dispatchOnFillRequestSuccess(PendingFillRequest.this, 234 response, request.getFlags()); 235 } 236 } 237 238 @Override 239 public void onFailure(int requestId, CharSequence message) { 240 if (!finish()) return; 241 242 final RemoteFillService remoteService = getService(); 243 if (remoteService != null) { 244 remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, 245 message); 246 } 247 } 248 }; 249 } 250 251 @Override 252 protected void onTimeout(RemoteFillService remoteService) { 253 // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is 254 // handled by the service, which could block. 255 final ICancellationSignal cancellation; 256 synchronized (mLock) { 257 cancellation = mCancellation; 258 } 259 if (cancellation != null) { 260 remoteService.dispatchOnFillTimeout(cancellation); 261 } 262 remoteService.dispatchOnFillRequestTimeout(PendingFillRequest.this); 263 } 264 265 @Override 266 public void run() { 267 synchronized (mLock) { 268 if (isCancelledLocked()) { 269 if (sDebug) Slog.d(mTag, "run() called after canceled: " + mRequest); 270 return; 271 } 272 } 273 final RemoteFillService remoteService = getService(); 274 if (remoteService != null) { 275 if (sVerbose) Slog.v(mTag, "calling onFillRequest() for id=" + mRequest.getId()); 276 try { 277 remoteService.mService.onFillRequest(mRequest, mCallback); 278 } catch (RemoteException e) { 279 Slog.e(mTag, "Error calling on fill request", e); 280 281 remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); 282 } 283 } 284 } 285 286 @Override 287 public boolean cancel() { 288 if (!super.cancel()) return false; 289 290 final ICancellationSignal cancellation; 291 synchronized (mLock) { 292 cancellation = mCancellation; 293 } 294 if (cancellation != null) { 295 try { 296 cancellation.cancel(); 297 } catch (RemoteException e) { 298 Slog.e(mTag, "Error cancelling a fill request", e); 299 } 300 } 301 return true; 302 } 303 } 304 305 private static final class PendingSaveRequest 306 extends PendingRequest<RemoteFillService, IAutoFillService> { 307 private final SaveRequest mRequest; 308 private final ISaveCallback mCallback; 309 310 public PendingSaveRequest(@NonNull SaveRequest request, 311 @NonNull RemoteFillService service) { 312 super(service); 313 mRequest = request; 314 315 mCallback = new ISaveCallback.Stub() { 316 @Override 317 public void onSuccess(IntentSender intentSender) { 318 if (!finish()) return; 319 320 final RemoteFillService remoteService = getService(); 321 if (remoteService != null) { 322 remoteService.dispatchOnSaveRequestSuccess(PendingSaveRequest.this, 323 intentSender); 324 } 325 } 326 327 @Override 328 public void onFailure(CharSequence message) { 329 if (!finish()) return; 330 331 final RemoteFillService remoteService = getService(); 332 if (remoteService != null) { 333 remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, 334 message); 335 } 336 } 337 }; 338 } 339 340 @Override 341 protected void onTimeout(RemoteFillService remoteService) { 342 remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); 343 } 344 345 @Override 346 public void run() { 347 final RemoteFillService remoteService = getService(); 348 if (remoteService != null) { 349 if (sVerbose) Slog.v(mTag, "calling onSaveRequest()"); 350 try { 351 remoteService.mService.onSaveRequest(mRequest, mCallback); 352 } catch (RemoteException e) { 353 Slog.e(mTag, "Error calling on save request", e); 354 355 remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); 356 } 357 } 358 } 359 360 @Override 361 public boolean isFinal() { 362 return true; 363 } 364 } 365 } 366