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