1 /* 2 * Copyright (C) 2018 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.augmented.Helper.logResponse; 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.annotation.UserIdInt; 27 import android.app.AppGlobals; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.pm.PackageManager; 31 import android.content.pm.ServiceInfo; 32 import android.os.Bundle; 33 import android.os.IBinder; 34 import android.os.ICancellationSignal; 35 import android.os.RemoteException; 36 import android.os.SystemClock; 37 import android.service.autofill.augmented.AugmentedAutofillService; 38 import android.service.autofill.augmented.IAugmentedAutofillService; 39 import android.service.autofill.augmented.IFillCallback; 40 import android.util.Pair; 41 import android.util.Slog; 42 import android.view.autofill.AutofillId; 43 import android.view.autofill.AutofillManager; 44 import android.view.autofill.AutofillValue; 45 import android.view.autofill.IAutoFillManagerClient; 46 47 import com.android.internal.infra.AbstractSinglePendingRequestRemoteService; 48 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 49 import com.android.internal.os.IResultReceiver; 50 51 final class RemoteAugmentedAutofillService 52 extends AbstractSinglePendingRequestRemoteService<RemoteAugmentedAutofillService, 53 IAugmentedAutofillService> { 54 55 private static final String TAG = RemoteAugmentedAutofillService.class.getSimpleName(); 56 57 private final int mIdleUnbindTimeoutMs; 58 private final int mRequestTimeoutMs; 59 RemoteAugmentedAutofillService(Context context, ComponentName serviceName, int userId, RemoteAugmentedAutofillServiceCallbacks callbacks, boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs, int requestTimeoutMs)60 RemoteAugmentedAutofillService(Context context, ComponentName serviceName, 61 int userId, RemoteAugmentedAutofillServiceCallbacks callbacks, 62 boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs, 63 int requestTimeoutMs) { 64 super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks, 65 context.getMainThreadHandler(), 66 bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, verbose); 67 mIdleUnbindTimeoutMs = idleUnbindTimeoutMs; 68 mRequestTimeoutMs = requestTimeoutMs; 69 70 // Bind right away. 71 scheduleBind(); 72 } 73 74 @Nullable getComponentName(@onNull String componentName, @UserIdInt int userId, boolean isTemporary)75 static Pair<ServiceInfo, ComponentName> getComponentName(@NonNull String componentName, 76 @UserIdInt int userId, boolean isTemporary) { 77 int flags = PackageManager.GET_META_DATA; 78 if (!isTemporary) { 79 flags |= PackageManager.MATCH_SYSTEM_ONLY; 80 } 81 82 final ComponentName serviceComponent; 83 ServiceInfo serviceInfo = null; 84 try { 85 serviceComponent = ComponentName.unflattenFromString(componentName); 86 serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags, 87 userId); 88 if (serviceInfo == null) { 89 Slog.e(TAG, "Bad service name for flags " + flags + ": " + componentName); 90 return null; 91 } 92 } catch (Exception e) { 93 Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e); 94 return null; 95 } 96 return new Pair<>(serviceInfo, serviceComponent); 97 } 98 99 @Override // from RemoteService handleOnConnectedStateChanged(boolean state)100 protected void handleOnConnectedStateChanged(boolean state) { 101 if (state && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) { 102 scheduleUnbind(); 103 } 104 try { 105 if (state) { 106 mService.onConnected(sDebug, sVerbose); 107 } else { 108 mService.onDisconnected(); 109 } 110 } catch (Exception e) { 111 Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e); 112 } 113 } 114 115 @Override // from AbstractRemoteService getServiceInterface(IBinder service)116 protected IAugmentedAutofillService getServiceInterface(IBinder service) { 117 return IAugmentedAutofillService.Stub.asInterface(service); 118 } 119 120 @Override // from AbstractRemoteService getTimeoutIdleBindMillis()121 protected long getTimeoutIdleBindMillis() { 122 return mIdleUnbindTimeoutMs; 123 } 124 125 @Override // from AbstractRemoteService getRemoteRequestMillis()126 protected long getRemoteRequestMillis() { 127 return mRequestTimeoutMs; 128 } 129 130 /** 131 * Called by {@link Session} to request augmented autofill. 132 */ onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client, int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue)133 public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client, 134 int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId, 135 @Nullable AutofillValue focusedValue) { 136 scheduleRequest(new PendingAutofillRequest(this, sessionId, client, taskId, 137 activityComponent, focusedId, focusedValue)); 138 } 139 140 @Override toString()141 public String toString() { 142 return "RemoteAugmentedAutofillService[" 143 + ComponentName.flattenToShortString(getComponentName()) + "]"; 144 } 145 146 /** 147 * Called by {@link Session} when it's time to destroy all augmented autofill requests. 148 */ onDestroyAutofillWindowsRequest()149 public void onDestroyAutofillWindowsRequest() { 150 scheduleAsyncRequest((s) -> s.onDestroyAllFillWindowsRequest()); 151 } 152 dispatchOnFillTimeout(@onNull ICancellationSignal cancellation)153 private void dispatchOnFillTimeout(@NonNull ICancellationSignal cancellation) { 154 mHandler.post(() -> { 155 try { 156 cancellation.cancel(); 157 } catch (RemoteException e) { 158 Slog.w(mTag, "Error calling cancellation signal: " + e); 159 } 160 }); 161 } 162 163 // TODO(b/123100811): inline into PendingAutofillRequest if it doesn't have any other subclass 164 private abstract static class MyPendingRequest 165 extends PendingRequest<RemoteAugmentedAutofillService, IAugmentedAutofillService> { 166 protected final int mSessionId; 167 MyPendingRequest(@onNull RemoteAugmentedAutofillService service, int sessionId)168 private MyPendingRequest(@NonNull RemoteAugmentedAutofillService service, int sessionId) { 169 super(service); 170 mSessionId = sessionId; 171 } 172 } 173 174 private static final class PendingAutofillRequest extends MyPendingRequest { 175 private final @NonNull AutofillId mFocusedId; 176 private final @Nullable AutofillValue mFocusedValue; 177 private final @NonNull IAutoFillManagerClient mClient; 178 private final @NonNull ComponentName mActivityComponent; 179 private final int mSessionId; 180 private final int mTaskId; 181 private final long mRequestTime = SystemClock.elapsedRealtime(); 182 private final @NonNull IFillCallback mCallback; 183 private ICancellationSignal mCancellation; 184 PendingAutofillRequest(@onNull RemoteAugmentedAutofillService service, int sessionId, @NonNull IAutoFillManagerClient client, int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue)185 protected PendingAutofillRequest(@NonNull RemoteAugmentedAutofillService service, 186 int sessionId, @NonNull IAutoFillManagerClient client, int taskId, 187 @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId, 188 @Nullable AutofillValue focusedValue) { 189 super(service, sessionId); 190 mClient = client; 191 mSessionId = sessionId; 192 mTaskId = taskId; 193 mActivityComponent = activityComponent; 194 mFocusedId = focusedId; 195 mFocusedValue = focusedValue; 196 mCallback = new IFillCallback.Stub() { 197 @Override 198 public void onSuccess() { 199 if (!finish()) return; 200 // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks 201 } 202 203 @Override 204 public void onCancellable(ICancellationSignal cancellation) { 205 synchronized (mLock) { 206 final boolean cancelled; 207 synchronized (mLock) { 208 mCancellation = cancellation; 209 cancelled = isCancelledLocked(); 210 } 211 if (cancelled) { 212 try { 213 cancellation.cancel(); 214 } catch (RemoteException e) { 215 Slog.e(mTag, "Error requesting a cancellation", e); 216 } 217 } 218 } 219 } 220 221 @Override 222 public boolean isCompleted() { 223 return isRequestCompleted(); 224 } 225 226 @Override 227 public void cancel() { 228 PendingAutofillRequest.this.cancel(); 229 } 230 }; 231 } 232 233 @Override run()234 public void run() { 235 synchronized (mLock) { 236 if (isCancelledLocked()) { 237 if (sDebug) Slog.d(mTag, "run() called after canceled"); 238 return; 239 } 240 } 241 final RemoteAugmentedAutofillService remoteService = getService(); 242 if (remoteService == null) return; 243 244 final IResultReceiver receiver = new IResultReceiver.Stub() { 245 246 @Override 247 public void send(int resultCode, Bundle resultData) throws RemoteException { 248 final IBinder realClient = resultData 249 .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT); 250 remoteService.mService.onFillRequest(mSessionId, realClient, mTaskId, 251 mActivityComponent, mFocusedId, mFocusedValue, mRequestTime, mCallback); 252 } 253 }; 254 255 // TODO(b/122728762): set cancellation signal, timeout (from both mClient and service), 256 // cache IAugmentedAutofillManagerClient reference, etc... 257 try { 258 mClient.getAugmentedAutofillClient(receiver); 259 } catch (RemoteException e) { 260 Slog.e(TAG, "exception handling getAugmentedAutofillClient() for " 261 + mSessionId + ": " + e); 262 finish(); 263 } 264 } 265 266 @Override onTimeout(RemoteAugmentedAutofillService remoteService)267 protected void onTimeout(RemoteAugmentedAutofillService remoteService) { 268 // TODO(b/122858578): must update the logged AUTOFILL_AUGMENTED_REQUEST with the 269 // timeout 270 Slog.w(TAG, "PendingAutofillRequest timed out (" + remoteService.mRequestTimeoutMs 271 + "ms) for " + remoteService); 272 // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks 273 final ICancellationSignal cancellation; 274 synchronized (mLock) { 275 cancellation = mCancellation; 276 } 277 if (cancellation != null) { 278 remoteService.dispatchOnFillTimeout(cancellation); 279 } 280 finish(); 281 logResponse(MetricsEvent.TYPE_ERROR, remoteService.getComponentName().getPackageName(), 282 mActivityComponent, mSessionId, remoteService.mRequestTimeoutMs); 283 } 284 285 @Override cancel()286 public boolean cancel() { 287 if (!super.cancel()) return false; 288 289 final ICancellationSignal cancellation; 290 synchronized (mLock) { 291 cancellation = mCancellation; 292 } 293 if (cancellation != null) { 294 try { 295 cancellation.cancel(); 296 } catch (RemoteException e) { 297 Slog.e(mTag, "Error cancelling an augmented fill request", e); 298 } 299 } 300 return true; 301 } 302 } 303 304 public interface RemoteAugmentedAutofillServiceCallbacks 305 extends VultureCallback<RemoteAugmentedAutofillService> { 306 // NOTE: so far we don't need to notify the callback implementation (an inner class on 307 // AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this 308 // callback interface is empty. 309 } 310 } 311