Yet another (major) refactoring on Content Capture and Augmented Autofill.
Bunch of changes:
- Split public SmartSuggestionsService info ContentCaptureService and
AugmentedAutofillService
- Renamed 'intelligence' packages to either 'contentcapture' or
'autofil.augmented'
- Renamed internal packages and classes.
- Changed permissions, resource names, etc...
- Moved Augmented Autofill logic from IntelligeceManagerService (R.I.P.) to
Autofill.
- Optimized IPCs by passing a String instead of the InteractionSessionId
(that also solves the view -> service dependency).
Test: atest CtsContentCaptureServiceTestCases \
CtsAutoFillServiceTestCases \
FrameworksCoreTests:SettingsBackupTest
Test: manual verification with Augmented Autofill Service
Bug: 119638877
Bug: 117944706
Change-Id: I787fc2a0dbd9ad53e4d5edb0d2a9242346e4652d
diff --git a/services/Android.bp b/services/Android.bp
index 3390438..58a0997 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -21,9 +21,9 @@
"services.autofill",
"services.backup",
"services.companion",
+ "services.contentcapture",
"services.coverage",
"services.devicepolicy",
- "services.intelligence",
"services.midi",
"services.net",
"services.print",
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 944ee33..e8887e7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -74,7 +74,6 @@
import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -100,6 +99,7 @@
private static final Object sLock = AutofillManagerService.class;
+ private static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
/**
* IME supports Smart Suggestions.
@@ -155,7 +155,7 @@
private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
private final LocalService mLocalService = new LocalService();
- final IntelligenceManagerInternal mIntelligenceManagerInternal;
+ private final ActivityManagerInternal mAm;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -184,7 +184,7 @@
public AutofillManagerService(Context context) {
super(context, UserManager.DISALLOW_AUTOFILL);
mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
- mIntelligenceManagerInternal = LocalServices.getService(IntelligenceManagerInternal.class);
+ mAm = LocalServices.getService(ActivityManagerInternal.class);
setLogLevelFromSettings();
setMaxPartitionsFromSettings();
@@ -288,6 +288,11 @@
return mSupportedSmartSuggestionModes;
}
+ // Called by AutofillManagerServiceImpl, doesn't need to check permission
+ boolean isInstantServiceAllowed() {
+ return mAllowInstantService;
+ }
+
// Called by Shell command.
void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
Slog.i(TAG, "destroySessions() for userId " + userId);
@@ -502,6 +507,39 @@
sFullScreenMode = mode;
}
+ // Called by Shell command.
+ void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName,
+ int durationMs) {
+ Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName
+ + " for " + durationMs + "ms");
+ enforceCallingPermissionForManagement();
+
+ Preconditions.checkNotNull(serviceName);
+ if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) {
+ throw new IllegalArgumentException("Max duration is "
+ + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")");
+ }
+
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.setTemporaryServiceLocked(serviceName,
+ durationMs);
+ }
+ }
+ }
+
+ // Called by Shell command
+ void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) {
+ enforceCallingPermissionForManagement();
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.resetTemporaryServiceLocked();
+ }
+ }
+ }
+
private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
com.android.server.autofill.Helper.sDebug = debug;
android.view.autofill.Helper.sDebug = debug;
@@ -877,14 +915,9 @@
throw new IllegalArgumentException(packageName + " is not a valid package", e);
}
- // TODO(b/113281366): rather than always call AM here, call it on demand on
- // getPreviousSessionsLocked()? That way we save space / time here, and don't set
- // a callback on AM unnecessarily (see TODO below :-)
- final ActivityManagerInternal am = LocalServices
- .getService(ActivityManagerInternal.class);
// TODO(b/113281366): add a callback method on AM to be notified when a task is finished
// so we can clean up sessions kept alive
- final int taskId = am.getTaskIdForActivity(activityToken, false);
+ final int taskId = mAm.getTaskIdForActivity(activityToken, false);
final int sessionId;
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3945c23..5a0d12c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -73,8 +73,11 @@
import com.android.server.LocalServices;
import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.AutofillManagerService.SmartSuggestionMode;
+import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractPerUserSystemService;
+import com.android.server.infra.AbstractRemoteService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.io.PrintWriter;
@@ -152,6 +155,19 @@
/** When was {@link PruneTask} last executed? */
private long mLastPrune = 0;
+ /**
+ * Object used to set the name of the augmented autofill service.
+ */
+ @NonNull
+ final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver;
+
+ /**
+ * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
+
AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState, boolean disabled) {
@@ -164,6 +180,12 @@
mUi = ui;
mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
mAutofillCompatState = autofillCompatState;
+
+ mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(),
+ userId, lock, com.android.internal.R.string.config_defaultAugmentedAutofillService);
+ mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
+ () -> updateRemoteAugmentedAutofillService());
+
updateLocked(disabled);
}
@@ -851,6 +873,12 @@
}
pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
.getString(R.string.config_defaultAutofillService));
+ pw.print(prefix); pw.print("mAugmentedAutofillNamer: ");
+ mAugmentedAutofillResolver.dumpShortLocked(pw); pw.println();
+ if (mRemoteAugmentedAutofillService != null) {
+ pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
+ mRemoteAugmentedAutofillService.dump(prefix2, pw);
+ }
pw.print(prefix); pw.print("Field classification enabled: ");
pw.println(isFieldClassificationEnabledLocked());
pw.print(prefix); pw.print("Compat pkgs: ");
@@ -992,6 +1020,52 @@
return null;
}
+ @GuardedBy("mLock")
+ @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
+ if (mRemoteAugmentedAutofillService == null) {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set");
+ }
+ return null;
+ }
+ final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
+ getContext(), serviceName, mUserId,
+ mAugmentedAutofillResolver.isTemporaryLocked());
+ if (componentName == null) return null;
+ if (sVerbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
+ }
+
+ mRemoteAugmentedAutofillService = new RemoteAugmentedAutofillService(getContext(),
+ componentName, mUserId, new RemoteAugmentedAutofillServiceCallbacks() {
+ @Override
+ public void onServiceDied(
+ AbstractRemoteService<? extends AbstractRemoteService<?>> service) {
+ // TODO(b/111330312): properly implement
+ Slog.w(TAG, "remote augmented autofill service died");
+ }
+ }, mMaster.isInstantServiceAllowed(), mMaster.verbose);
+ }
+
+ return mRemoteAugmentedAutofillService;
+ }
+
+ /**
+ * Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
+ */
+ private void updateRemoteAugmentedAutofillService() {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
+ if (mRemoteAugmentedAutofillService != null) {
+ mRemoteAugmentedAutofillService.destroy();
+ mRemoteAugmentedAutofillService = null;
+ }
+ }
+ }
+
private void sendStateToClients(boolean resetClient) {
final RemoteCallbackList<IAutoFillManagerClient> clients;
final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 522280e..35c5102 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -104,6 +104,11 @@
pw.println(" set bind-instant-service-allowed [true | false]");
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
+ pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
+ pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
+ pw.println(" To reset, call with just the USER_ID argument.");
+ pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
pw.println("");
@@ -151,6 +156,8 @@
return setFullScreenMode(pw);
case "bind-instant-service-allowed":
return setBindInstantService(pw);
+ case "temporary-augmented-service":
+ return setTemporaryAugmentedService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -293,6 +300,20 @@
}
}
+ private int setTemporaryAugmentedService(PrintWriter pw) {
+ final int userId = getNextIntArgRequired();
+ final String serviceName = getNextArg();
+ if (serviceName == null) {
+ mService.resetTemporaryAugmentedAutofillService(userId);
+ return 0;
+ }
+ final int duration = getNextIntArgRequired();
+ mService.setTemporaryAugmentedAutofillService(userId, serviceName, duration);
+ pw.println("AugmentedAutofillService temporarily set to " + serviceName + " for "
+ + duration + "ms");
+ return 0;
+ }
+
private int requestDestroy(PrintWriter pw) {
if (!isNextArgSessions(pw)) {
return -1;
@@ -371,4 +392,8 @@
}
return UserHandle.USER_ALL;
}
+
+ private int getNextIntArgRequired() {
+ return Integer.parseInt(getNextArgRequired());
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
new file mode 100644
index 0000000..222888c
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService;
+import android.service.autofill.augmented.IAugmentedAutofillService;
+import android.service.autofill.augmented.IFillCallback;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAutoFillManagerClient;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.server.infra.AbstractSinglePendingRequestRemoteService;
+
+final class RemoteAugmentedAutofillService
+ extends AbstractSinglePendingRequestRemoteService<RemoteAugmentedAutofillService> {
+
+ private static final String TAG = RemoteAugmentedAutofillService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final RemoteAugmentedAutofillServiceCallbacks mCallbacks;
+ private IAugmentedAutofillService mService;
+
+ RemoteAugmentedAutofillService(Context context, ComponentName serviceName,
+ int userId, RemoteAugmentedAutofillServiceCallbacks callbacks,
+ boolean bindInstantServiceAllowed, boolean verbose) {
+ super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
+ bindInstantServiceAllowed, verbose);
+ mCallbacks = callbacks;
+ }
+
+ @Nullable
+ public static ComponentName getComponentName(@NonNull Context context,
+ @NonNull String componentName, @UserIdInt int userId, boolean isTemporary) {
+ int flags = PackageManager.GET_META_DATA;
+ if (!isTemporary) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
+ final ComponentName serviceComponent;
+ ServiceInfo serviceInfo = null;
+ try {
+ serviceComponent = ComponentName.unflattenFromString(componentName);
+ serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags,
+ userId);
+ if (serviceInfo == null) {
+ Slog.e(TAG, "Bad service name for flags " + flags + ": " + componentName);
+ return null;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
+ return null;
+ }
+ return serviceComponent;
+ }
+
+ @Override // from AbstractRemoteService
+ protected IInterface getServiceInterface(IBinder service) {
+ mService = IAugmentedAutofillService.Stub.asInterface(service);
+ return mService;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getTimeoutIdleBindMillis() {
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getRemoteRequestMillis() {
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link Session} to request augmented autofill.
+ */
+ public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client,
+ int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingAutofillRequest(this, sessionId, client, taskId,
+ activityComponent, focusedId, focusedValue));
+ }
+
+ /**
+ * Called by {@link Session} when it's time to destroy all augmented autofill requests.
+ */
+ public void onDestroyAutofillWindowsRequest(int sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteAugmentedAutofillService> {
+ protected final int mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteAugmentedAutofillService service, int sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+ }
+
+ private static final class PendingAutofillRequest extends MyPendingRequest {
+ private final @NonNull AutofillId mFocusedId;
+ private final @Nullable AutofillValue mFocusedValue;
+ private final @NonNull IAutoFillManagerClient mClient;
+ private final @NonNull ComponentName mActivityComponent;
+ private final int mTaskId;
+ private final long mRequestTime = SystemClock.elapsedRealtime();
+ private final @NonNull IFillCallback mCallback;
+
+ protected PendingAutofillRequest(@NonNull RemoteAugmentedAutofillService service,
+ int sessionId, @NonNull IAutoFillManagerClient client, int taskId,
+ @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ super(service, sessionId);
+ mClient = client;
+ mTaskId = taskId;
+ mActivityComponent = activityComponent;
+ mFocusedId = focusedId;
+ mFocusedValue = focusedValue;
+ mCallback = new IFillCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ if (!finish()) return;
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ }
+ };
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ final IResultReceiver receiver = new IResultReceiver.Stub() {
+
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ final IBinder realClient = resultData
+ .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
+ remoteService.mService.onFillRequest(mSessionId, realClient, mTaskId,
+ mActivityComponent, mFocusedId, mFocusedValue, mRequestTime, mCallback);
+ }
+ };
+
+ // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
+ // cache IAugmentedAutofillManagerClient reference, etc...
+ try {
+ mClient.getAugmentedAutofillClient(receiver);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "exception handling getAugmentedAutofillClient() for "
+ + mSessionId + ": " + e);
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ Slog.wtf(TAG, "timed out: " + this);
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ finish();
+ }
+
+ }
+
+ private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
+
+ protected PendingDestroyAutofillWindowsRequest(
+ @NonNull RemoteAugmentedAutofillService service, @NonNull int sessionId) {
+ super(service, sessionId);
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ try {
+ remoteService.mService.onDestroyFillWindowRequest(mSessionId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling onDestroyAutofillWindowsRequest() for "
+ + mSessionId + ": " + e);
+ } finally {
+ // Service is not calling back, so we finish right away.
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ // Should not happen because we called finish() on run(), although currently it might
+ // be called if the service is destroyed while showing it.
+ Slog.e(TAG, "timed out: " + this);
+ }
+ }
+
+ public interface RemoteAugmentedAutofillServiceCallbacks extends VultureCallback {
+ // NOTE: so far we don't need to notify the callback implementation (an inner class on
+ // AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this
+ // callback interface is empty.
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index fb64cb2..d76a5df 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,8 +99,6 @@
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -248,9 +246,18 @@
@GuardedBy("mLock")
private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
+ /**
+ * Destroys the augmented Autofill UI.
+ */
+ // TODO(b/111330312): this runnable is called when the Autofill session is destroyed, the
+ // main reason being the cases where user tap HOME.
+ // Right now it's completely destroying the UI, but we need to decide whether / how to
+ // properly recover it later (for example, if the user switches back to the activity,
+ // should it be restored? Right not it kind of is, because Autofill's Session trigger a
+ // new FillRequest, which in turn triggers the Augmented Autofill request again)
@GuardedBy("mLock")
@Nullable
- private AugmentedAutofillCallback mAugmentedAutofillCallback;
+ private Runnable mAugmentedAutofillDestroyer;
/**
* Receiver of assist data from the app's {@link Activity}.
@@ -2516,8 +2523,8 @@
// The default autofill service cannot fullfill the request, let's check if the intelligence
// service can.
- mAugmentedAutofillCallback = triggerAugmentedAutofillLocked();
- if (mAugmentedAutofillCallback == null) {
+ mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked();
+ if (mAugmentedAutofillDestroyer == null) {
if (sVerbose) {
Slog.v(TAG, "canceling session " + id + " when server returned null and there is no"
+ " AugmentedAutofill for user");
@@ -2539,21 +2546,22 @@
/**
* Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
*
- * @return callback to the Augmented Autofill service, or {@code null} if not supported.
+ * @return callback to destroy the autofill UI, or {@code null} if not supported.
*/
// TODO(b/111330312): might need to call it in other places, like when the service returns a
// non-null response but without datasets (for example, just SaveInfo)
@GuardedBy("mLock")
- private AugmentedAutofillCallback triggerAugmentedAutofillLocked() {
+ private Runnable triggerAugmentedAutofillLocked() {
// Check if Smart Suggestions is supported...
final @SmartSuggestionMode int supportedModes = mService
.getSupportedSmartSuggestionModesLocked();
if (supportedModes == 0) return null;
// ...then if the service is set for the user
- final IntelligenceManagerInternal intelligenceManagerInternal = mService
- .getMaster().mIntelligenceManagerInternal;
- if (intelligenceManagerInternal == null) return null;
+
+ final RemoteAugmentedAutofillService remoteService = mService
+ .getRemoteAugmentedAutofillServiceLocked();
+ if (remoteService == null) return null;
// Define which mode will be used
final int mode;
@@ -2584,8 +2592,13 @@
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
// furgher AFM -> AFMS calls.
// TODO(b/119638958): add CTS tests
- return intelligenceManagerInternal.requestAutofill(mService.getUserId(), mClient,
- mActivityToken, this.id, mCurrentViewId, currentValue);
+ remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, mCurrentViewId,
+ currentValue);
+
+ if (mAugmentedAutofillDestroyer == null) {
+ mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(id);
+ }
+ return mAugmentedAutofillDestroyer;
}
@GuardedBy("mLock")
@@ -2866,8 +2879,8 @@
pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println(
mSaveOnAllViewsInvisible);
pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
- if (mAugmentedAutofillCallback != null) {
- pw.print(prefix); pw.println("has AugmentedAutofillCallback");
+ if (mAugmentedAutofillDestroyer != null) {
+ pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
}
mRemoteFillService.dump(prefix, pw);
}
@@ -3045,8 +3058,9 @@
@GuardedBy("mLock")
void destroyAugmentedAutofillWindowsLocked() {
- if (mAugmentedAutofillCallback != null) {
- mAugmentedAutofillCallback.destroy();
+ if (mAugmentedAutofillDestroyer != null) {
+ mAugmentedAutofillDestroyer.run();
+ mAugmentedAutofillDestroyer = null;
}
}
diff --git a/services/intelligence/Android.bp b/services/contentcapture/Android.bp
similarity index 69%
rename from services/intelligence/Android.bp
rename to services/contentcapture/Android.bp
index 2df1235..57e859e 100644
--- a/services/intelligence/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,5 @@
java_library_static {
- name: "services.intelligence",
+ name: "services.contentcapture",
srcs: ["java/**/*.java"],
libs: ["services.core"],
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
similarity index 68%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index a760cbd..872fe42 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static android.Manifest.permission.MANAGE_SMART_SUGGESTIONS;
+import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import android.annotation.NonNull;
@@ -32,13 +32,9 @@
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
-import android.service.intelligence.InteractionSessionId;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.IIntelligenceManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -58,11 +54,10 @@
* <p>The data collected by this service can be analyzed and combined with other sources to provide
* contextual data in other areas of the system such as Autofill.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceManagerService extends
- AbstractMasterSystemService<IntelligenceManagerService, IntelligencePerUserService> {
+public final class ContentCaptureManagerService extends
+ AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
- private static final String TAG = "IntelligenceManagerService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
@@ -73,32 +68,32 @@
private final LocalService mLocalService = new LocalService();
- public IntelligenceManagerService(Context context) {
- super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
+ public ContentCaptureManagerService(Context context) {
+ super(context, UserManager.DISALLOW_CONTENT_CAPTURE);
}
@Override // from AbstractMasterSystemService
- protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
+ protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
- return new IntelligencePerUserService(this, mLock, resolvedUserId);
+ return new ContentCapturePerUserService(this, mLock, resolvedUserId);
}
@Override // from SystemService
public void onStart() {
publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE,
- new IntelligenceManagerServiceStub());
- publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+ new ContentCaptureManagerServiceStub());
+ publishLocalService(ContentCaptureManagerInternal.class, mLocalService);
}
@Override // from AbstractMasterSystemService
- protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+ protected void onServiceRemoved(@NonNull ContentCapturePerUserService service,
@UserIdInt int userId) {
service.destroyLocked();
}
@Override // from AbstractMasterSystemService
protected void enforceCallingPermissionForManagement() {
- getContext().enforceCallingPermission(MANAGE_SMART_SUGGESTIONS, TAG);
+ getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG);
}
@Override // from AbstractMasterSystemService
@@ -113,7 +108,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.destroySessionsLocked();
}
@@ -139,7 +134,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.listSessionsLocked(sessions);
}
@@ -165,11 +160,11 @@
return mAm;
}
- final class IntelligenceManagerServiceStub extends IIntelligenceManager.Stub {
+ final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@Override
public void startSession(@UserIdInt int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+ @NonNull ComponentName componentName, @NonNull String sessionId,
int flags, @NonNull IResultReceiver result) {
Preconditions.checkNotNull(activityToken);
Preconditions.checkNotNull(componentName);
@@ -183,31 +178,31 @@
final int displayId = 0;
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, componentName, taskId, displayId,
sessionId, flags, mAllowInstantService, result);
}
}
@Override
- public void sendEvents(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void sendEvents(@UserIdInt int userId, @NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
Preconditions.checkNotNull(events);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.sendEventsLocked(sessionId, events);
}
}
@Override
- public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void finishSession(@UserIdInt int userId, @NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.finishSessionLocked(sessionId, events);
}
}
@@ -225,19 +220,19 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
- new IntelligenceServiceShellCommand(IntelligenceManagerService.this).exec(
+ new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec(
this, in, out, err, args, callback, resultReceiver);
}
}
- private final class LocalService extends IntelligenceManagerInternal {
+ private final class LocalService extends ContentCaptureManagerInternal {
@Override
- public boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId) {
+ public boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
- return service.isIntelligenceServiceForUserLocked(uid);
+ return service.isContentCaptureServiceForUserLocked(uid);
}
}
return false;
@@ -247,27 +242,12 @@
public boolean sendActivityAssistData(@UserIdInt int userId, @NonNull IBinder activityToken,
@NonNull Bundle data) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
return service.sendActivityAssistDataLocked(activityToken, data);
}
}
return false;
}
-
- @Override
- public AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
- if (service != null) {
- return service.requestAutofill(client, activityToken, autofillSessionId,
- focusedId, focusedValue);
- }
- }
- return null;
- }
}
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
similarity index 89%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 0d92a972..2f78276 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static com.android.server.intelligence.IntelligenceManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
+import static com.android.server.contentcapture.ContentCaptureManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
import android.annotation.NonNull;
import android.os.Bundle;
@@ -30,14 +30,13 @@
import java.util.concurrent.TimeUnit;
/**
- * Shell Command implementation for {@link IntelligenceManagerService}.
+ * Shell Command implementation for {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceServiceShellCommand extends ShellCommand {
+public final class ContentCaptureManagerServiceShellCommand extends ShellCommand {
- private final IntelligenceManagerService mService;
+ private final ContentCaptureManagerService mService;
- public IntelligenceServiceShellCommand(@NonNull IntelligenceManagerService service) {
+ public ContentCaptureManagerServiceShellCommand(@NonNull ContentCaptureManagerService service) {
mService = service;
}
@@ -64,8 +63,7 @@
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
- // TODO(b/111276913): rename "intelligence" once SELinux rule changed
- pw.println("Intelligence Service (intelligence) commands:");
+ pw.println("ContentCapture Service (content_capture) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
@@ -106,7 +104,7 @@
case "bind-instant-service-allowed":
return setBindInstantService(pw);
case "temporary-service":
- return setTemporaryService();
+ return setTemporaryService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -137,7 +135,7 @@
}
}
- private int setTemporaryService() {
+ private int setTemporaryService(PrintWriter pw) {
final int userId = getNextIntArgRequired();
final String serviceName = getNextArg();
if (serviceName == null) {
@@ -146,6 +144,8 @@
}
final int duration = getNextIntArgRequired();
mService.setTemporaryService(userId, serviceName, duration);
+ pw.println("ContentCaptureService temporarily set to " + serviceName + " for "
+ + duration + "ms");
return 0;
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
similarity index 77%
rename from services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index e2b8d48..aa171f4 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -34,46 +34,40 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
- * Per-user instance of {@link IntelligenceManagerService}.
+ * Per-user instance of {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-final class IntelligencePerUserService
- extends AbstractPerUserSystemService<IntelligencePerUserService,
- IntelligenceManagerService> {
+final class ContentCapturePerUserService
+ extends
+ AbstractPerUserSystemService<ContentCapturePerUserService, ContentCaptureManagerService> {
- private static final String TAG = "IntelligencePerUserService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
@GuardedBy("mLock")
- private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+ private final ArrayMap<String, ContentCaptureSession> mSessions =
new ArrayMap<>();
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
- protected IntelligencePerUserService(
- IntelligenceManagerService master, Object lock, @UserIdInt int userId) {
+ protected ContentCapturePerUserService(
+ ContentCaptureManagerService master, Object lock, @UserIdInt int userId) {
super(master, new FrameworkResourcesServiceNameResolver(master.getContext(), userId, lock,
- com.android.internal.R.string.config_defaultSmartSuggestionsService), lock, userId);
+ com.android.internal.R.string.config_defaultContentCaptureService), lock, userId);
}
@Override // from PerUserSystemService
@@ -98,12 +92,12 @@
+ " " + serviceComponent.flattenToShortString());
return null;
}
- if (!Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE.equals(si.permission)) {
- Slog.w(TAG, "SmartSuggestionsService from '" + si.packageName
+ if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+ Slog.w(TAG, "ContentCaptureService from '" + si.packageName
+ "' does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
throw new SecurityException("Service does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
}
return si;
}
@@ -119,7 +113,7 @@
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
@NonNull ComponentName componentName, int taskId, int displayId,
- @NonNull InteractionSessionId sessionId, int flags, boolean bindInstantServiceAllowed,
+ @NonNull String sessionId, int flags, boolean bindInstantServiceAllowed,
@NonNull IResultReceiver resultReceiver) {
if (!isEnabledLocked()) {
sendToClient(resultReceiver, ContentCaptureManager.STATE_DISABLED);
@@ -163,7 +157,7 @@
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
- public void finishSessionLocked(@NonNull InteractionSessionId sessionId,
+ public void finishSessionLocked(@NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -180,7 +174,7 @@
// TODO(b/111276913): for now we're sending the events and the onDestroy() in 2 separate
// calls because it's not clear yet whether we'll change the manager to send events
// to the service directly (i.e., without passing through system server). Once we
- // decide, we might need to split IIntelligenceService.onSessionLifecycle() in 2
+ // decide, we might need to split IContentCaptureManager.onSessionLifecycle() in 2
// methods, one for start and another for finish (and passing the events to finish),
// otherwise the service might receive the 2 calls out of order.
session.sendEventsLocked(events);
@@ -193,9 +187,9 @@
}
// TODO(b/111276913): need to figure out why some events are sent before session is started;
- // probably because IntelligenceManager is not buffering them until it gets the session back
+ // probably because ContentCaptureManager is not buffering them until it gets the session back
@GuardedBy("mLock")
- public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+ public void sendEventsLocked(@NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -216,7 +210,7 @@
@GuardedBy("mLock")
public boolean sendActivityAssistDataLocked(@NonNull IBinder activityToken,
@NonNull Bundle data) {
- final InteractionSessionId id = getInteractionSessionId(activityToken);
+ final String id = getSessionId(activityToken);
if (id != null) {
final ContentCaptureSession session = mSessions.get(id);
final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
@@ -233,12 +227,12 @@
}
@GuardedBy("mLock")
- public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+ public void removeSessionLocked(@NonNull String sessionId) {
mSessions.remove(sessionId);
}
@GuardedBy("mLock")
- public boolean isIntelligenceServiceForUserLocked(int uid) {
+ public boolean isContentCaptureServiceForUserLocked(int uid) {
return uid == getServiceUidLocked();
}
@@ -283,24 +277,6 @@
}
}
- public AugmentedAutofillCallback requestAutofill(@NonNull IAutoFillManagerClient client,
- @NonNull IBinder activityToken, int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final ContentCaptureSession session = getSession(activityToken);
- if (session != null) {
- // TODO(b/111330312): log metrics
- if (mMaster.verbose) Slog.v(TAG, "requestAugmentedAutofill()");
- return session.requestAutofillLocked(client, autofillSessionId, focusedId,
- focusedValue);
- }
- if (mMaster.debug) {
- Slog.d(TAG, "requestAutofill(): no session for " + activityToken);
- }
- return null;
- }
- }
-
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -319,10 +295,10 @@
}
/**
- * Returns the InteractionSessionId associated with the given activity.
+ * Returns the session id associated with the given activity.
*/
@GuardedBy("mLock")
- private InteractionSessionId getInteractionSessionId(@NonNull IBinder activityToken) {
+ private String getSessionId(@NonNull IBinder activityToken) {
for (int i = 0; i < mSessions.size(); i++) {
ContentCaptureSession session = mSessions.valueAt(i);
if (session.isActivitySession(activityToken)) {
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
similarity index 63%
rename from services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
index 05b8201..2302b7d 100644
--- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
@@ -13,55 +13,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SmartSuggestionsService;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.InteractionSessionId;
+import android.service.contentcapture.SnapshotData;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
-import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
import java.io.PrintWriter;
import java.util.List;
-final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
+final class ContentCaptureSession implements ContentCaptureServiceCallbacks {
private static final String TAG = "ContentCaptureSession";
private final Object mLock;
final IBinder mActivityToken;
- private final IntelligencePerUserService mService;
- private final RemoteIntelligenceService mRemoteService;
+ private final ContentCapturePerUserService mService;
+ private final RemoteContentCaptureService mRemoteService;
private final InteractionContext mInterationContext;
- private final InteractionSessionId mId;
- private AugmentedAutofillCallback mAutofillCallback;
+ private final String mId;
ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
- @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
+ @NonNull IBinder activityToken, @NonNull ContentCapturePerUserService service,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
- int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
+ int taskId, int displayId, @NonNull String sessionId, int flags,
boolean bindInstantServiceAllowed, boolean verbose) {
mLock = lock;
mActivityToken = activityToken;
mService = service;
mId = Preconditions.checkNotNull(sessionId);
- mRemoteService = new RemoteIntelligenceService(context,
- SmartSuggestionsService.SERVICE_INTERFACE, serviceComponentName, userId, this,
+ mRemoteService = new RemoteContentCaptureService(context,
+ ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, userId, this,
bindInstantServiceAllowed, verbose);
mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
}
@@ -74,7 +68,7 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} that the service started.
+ * Notifies the {@link ContentCaptureService} that the service started.
*/
@GuardedBy("mLock")
public void notifySessionStartedLocked() {
@@ -82,14 +76,14 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} of a batch of events.
+ * Notifies the {@link ContentCaptureService} of a batch of events.
*/
public void sendEventsLocked(@NonNull List<ContentCaptureEvent> events) {
mRemoteService.onContentCaptureEventsRequest(mId, events);
}
/**
- * Notifies the {@link SmartSuggestionsService} of a snapshot of an activity.
+ * Notifies the {@link ContentCaptureService} of a snapshot of an activity.
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
@@ -97,24 +91,10 @@
}
/**
- * Requests the service to autofill the given field.
- */
- public AugmentedAutofillCallback requestAutofillLocked(@NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- mRemoteService.onRequestAutofillLocked(mId, client, autofillSessionId, focusedId,
- focusedValue);
- if (mAutofillCallback == null) {
- mAutofillCallback = () -> mRemoteService.onDestroyAutofillWindowsRequest(mId);
- }
- return mAutofillCallback;
- }
-
- /**
* Cleans up the session and removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -130,7 +110,7 @@
* Cleans up the session, but not removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -138,11 +118,6 @@
if (mService.isVerbose()) {
Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
}
- if (mAutofillCallback != null) {
- mAutofillCallback.destroy();
- mAutofillCallback = null;
- }
-
// TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
if (notifyRemoteService) {
mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
@@ -173,19 +148,18 @@
@GuardedBy("mLock")
public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("id: "); mId.dump(pw); pw.println();
+ pw.print(prefix); pw.print("id: "); pw.print(mId); pw.println();
pw.print(prefix); pw.print("context: "); mInterationContext.dump(pw); pw.println();
pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("has autofill callback: ");
- pw.println(mAutofillCallback != null);
}
String toShortString() {
- return mId.getValue() + ":" + mActivityToken;
+ return mId + ":" + mActivityToken;
}
@Override
public String toString() {
- return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+ return "ContentCaptureSession[id=" + mId + ", act=" + mActivityToken + "]";
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
new file mode 100644
index 0000000..6a111f2
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
+
+import java.util.List;
+
+final class RemoteContentCaptureService
+ extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService> {
+
+ private static final String TAG = RemoteContentCaptureService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final ContentCaptureServiceCallbacks mCallbacks;
+ private IContentCaptureService mService;
+
+ RemoteContentCaptureService(Context context, String serviceInterface,
+ ComponentName componentName, int userId,
+ ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+ boolean verbose) {
+ super(context, serviceInterface, componentName, userId, callbacks,
+ bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+ mCallbacks = callbacks;
+ }
+
+ @Override // from RemoteService
+ protected IInterface getServiceInterface(@NonNull IBinder service) {
+ mService = IContentCaptureService.Stub.asInterface(service);
+ return mService;
+ }
+
+ // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
+ @Override // from RemoteService
+ protected long getTimeoutIdleBindMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from RemoteService
+ protected long getRemoteRequestMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to generate a call to the
+ * {@link RemoteContentCaptureService} to indicate the session was created (when {@code context}
+ * is not {@code null} or destroyed (when {@code context} is {@code null}).
+ */
+ public void onSessionLifecycleRequest(@Nullable InteractionContext context,
+ @NonNull String sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+ */
+ public void onContentCaptureEventsRequest(@NonNull String sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send snapshot data to the service.
+ */
+ public void onActivitySnapshotRequest(@NonNull String sessionId,
+ @NonNull SnapshotData snapshotData) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteContentCaptureService> {
+ protected final String mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+
+ @Override // from PendingRequest
+ protected final void onTimeout(RemoteContentCaptureService remoteService) {
+ Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+ + mSessionId);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+ }
+
+ @Override // from PendingRequest
+ public final void run() {
+ final RemoteContentCaptureService remoteService = getService();
+ if (remoteService != null) {
+ try {
+ // We don't expect the service to call us back, so we finish right away.
+ myRun(remoteService);
+ // TODO(b/111330312): not true anymore!!
+ finish();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+ + mSessionId + ": " + e);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
+ }
+ }
+ }
+
+ protected abstract void myRun(@NonNull RemoteContentCaptureService service)
+ throws RemoteException;
+
+ }
+
+ private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+ private final InteractionContext mContext;
+
+ protected PendingSessionLifecycleRequest(@NonNull RemoteContentCaptureService service,
+ @Nullable InteractionContext context, @NonNull String sessionId) {
+ super(service, sessionId);
+ mContext = context;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+ }
+ }
+
+ private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+ private final List<ContentCaptureEvent> mEvents;
+
+ protected PendingOnContentCaptureEventsRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull List<ContentCaptureEvent> events) {
+ super(service, sessionId);
+ mEvents = events;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onContentCaptureEventsRequest(mSessionId,
+ new ContentCaptureEventsRequest(mEvents));
+ }
+ }
+
+ private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
+
+ private final SnapshotData mSnapshotData;
+
+ protected PendingOnActivitySnapshotRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull SnapshotData snapshotData) {
+ super(service, sessionId);
+ mSnapshotData = snapshotData;
+ }
+
+ @Override // from MyPendingRequest
+ protected void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
+ }
+ }
+
+ public interface ContentCaptureServiceCallbacks extends VultureCallback {
+ // To keep it simple, we use the same callback for all failures / timeouts.
+ void onFailureOrTimeout(boolean timedOut);
+ }
+}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 65537ad..258c325 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,7 +55,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -158,7 +158,7 @@
private final IUserManager mUm;
private final PackageManager mPm;
private final AppOpsManager mAppOps;
- private final IntelligenceManagerInternal mIm;
+ private final ContentCaptureManagerInternal mContentCaptureInternal;
private final IBinder mPermissionOwner;
private HostClipboardMonitor mHostClipboardMonitor = null;
private Thread mHostMonitorThread = null;
@@ -178,7 +178,7 @@
mPm = getContext().getPackageManager();
mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
- mIm = LocalServices.getService(IntelligenceManagerInternal.class);
+ mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
@@ -652,9 +652,10 @@
case AppOpsManager.OP_READ_CLIPBOARD:
// Clipboard can only be read by applications with focus..
boolean allowed = mWm.isUidFocused(callingUid);
- if (!allowed && mIm != null) {
+ if (!allowed && mContentCaptureInternal != null) {
// ...or the Intelligence Service
- allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
+ allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
+ userId);
}
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
new file mode 100644
index 0000000..726362a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * ContentCapture Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class ContentCaptureManagerInternal {
+
+ /**
+ * Checks whether the given {@code uid} owns the
+ * {@link android.service.contentcapture.ContentCaptureService} implementation associated with
+ * the given {@code userId}.
+ */
+ public abstract boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId);
+
+ /**
+ * Notifies the intelligence service of new assist data for the given activity.
+ *
+ * @return {@code false} if there was no service set for the given user
+ */
+ public abstract boolean sendActivityAssistData(@UserIdInt int userId,
+ @NonNull IBinder activityToken, @NonNull Bundle data);
+}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index ef9ad8a..c0c4a6e 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -58,7 +58,7 @@
* <ul>
* <li>Disabling the service when {@link UserManager} restrictions change.
* <li>Refreshing the service when its underlying
- * {@link #getSettingsProperty() Settings property} changed.
+ * {@link #getServiceSettingsProperty() Settings property} changed.
* <li>Calling the service when other Settings properties changed.
* </ul>
*
diff --git a/services/core/java/com/android/server/infra/AbstractRemoteService.java b/services/core/java/com/android/server/infra/AbstractRemoteService.java
index 7af1d4c..67b3ecf 100644
--- a/services/core/java/com/android/server/infra/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractRemoteService.java
@@ -248,7 +248,7 @@
if (checkIfDestroyed() || mCompleted) return;
if (!handleIsBound()) {
- if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing" + pendingRequest);
+ if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing " + pendingRequest);
handlePendingRequestWhileUnBound(pendingRequest);
handleEnsureBound();
} else {
@@ -379,6 +379,7 @@
final S remoteService = mWeakService.get();
if (remoteService != null) {
+ // TODO(b/117779333): we should probably ignore it if service is destroyed.
Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
onTimeout(remoteService);
} else {
diff --git a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
index 8f8b448..37a1f54 100644
--- a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
@@ -73,7 +73,8 @@
void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) {
if (mPendingRequest != null) {
if (mVerbose) {
- Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest);
+ Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest
+ + " to handle " + pendingRequest);
}
mPendingRequest.cancel();
}
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
deleted file mode 100644
index f424869..0000000
--- a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-
-/**
- * Intelligence Manager local system service interface.
- *
- * @hide Only for use within the system server.
- */
-//TODO(b/111276913): rename once the final name is defined
-public abstract class IntelligenceManagerInternal {
-
- /**
- * Checks whether the given {@code uid} owns the
- * {@link android.service.intelligence.SmartSuggestionsService} implementation associated with
- * the given {@code userId}.
- */
- public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
-
- /**
- * Notifies the intelligence service of new assist data for the given activity.
- *
- * @return {@code false} if there was no service set for the given user
- */
- public abstract boolean sendActivityAssistData(@UserIdInt int userId,
- @NonNull IBinder activityToken, @NonNull Bundle data);
-
- /**
- * Asks the intelligence service to provide Augmented Autofill for a given activity.
- *
- * @param userId user handle
- * @param client binder used to communicate with the activity that originated this request.
- * @param activityToken activity that originated this request.
- * @param autofillSessionId autofill session id (must be used on {@code client} calls.
- * @param focusedId id of the the field that triggered this request.
- * @param focusedValue current value of the field that triggered this request.
- *
- * @return {@code false} if the service cannot handle this request, {@code true} otherwise.
- * <b>NOTE: </b> it must return right away; typically it will return {@code false} if the
- * service is disabled (or the activity blacklisted).
- */
- public abstract AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue);
-
- /**
- * Callback used by the Autofill Session to communicate with the Augmented Autofill service.
- */
- public interface AugmentedAutofillCallback {
- // TODO(b/111330312): this method is calling when the Autofill session is destroyed, the
- // main reason being the cases where user tap HOME.
- // Right now it's completely destroying the UI, but we need to decide whether / how to
- // properly recover it later (for example, if the user switches back to the activity,
- // should it be restored? Right not it kind of is, because Autofill's Session trigger a
- // new FillRequest, which in turn triggers the Augmented Autofill request again)
- /**
- * Destroys the Autofill UI.
- */
- void destroy();
- }
-}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 1e287b4..9422182 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -47,7 +47,7 @@
import com.android.server.LocalServices;
import com.android.server.am.AssistDataRequester;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
import java.util.List;
@@ -225,8 +225,8 @@
public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
int activityCount) {
// Try to notify the intelligence service first
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder activityToken = topActivities.get(activityIndex);
if (imService == null
|| !imService.sendActivityAssistData(userId, activityToken, data)) {
@@ -236,8 +236,8 @@
}
};
} else {
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
if (imService == null) {
// There is no intelligence service, so there is no point requesting assist data
return;
diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
deleted file mode 100644
index c4fbdca..0000000
--- a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.IIntelligenceService;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
-
-import java.util.List;
-
-//TODO(b/111276913): rename once the final name is defined
-final class RemoteIntelligenceService
- extends AbstractMultiplePendingRequestsRemoteService<RemoteIntelligenceService> {
-
- private static final String TAG = "RemoteIntelligenceService";
-
- private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
- private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
-
- private final RemoteIntelligenceServiceCallbacks mCallbacks;
- private IIntelligenceService mService;
-
- RemoteIntelligenceService(Context context, String serviceInterface,
- ComponentName componentName, int userId,
- RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
- boolean verbose) {
- super(context, serviceInterface, componentName, userId, callbacks,
- bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
- mCallbacks = callbacks;
- }
-
- @Override // from RemoteService
- protected IInterface getServiceInterface(@NonNull IBinder service) {
- mService = IIntelligenceService.Stub.asInterface(service);
- return mService;
- }
-
- // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
- @Override // from RemoteService
- protected long getTimeoutIdleBindMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_IDLE_BIND_MILLIS;
- }
-
- @Override // from RemoteService
- protected long getRemoteRequestMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_REMOTE_REQUEST_MILLIS;
- }
-
- /**
- * Called by {@link ContentCaptureSession} to generate a call to the
- * {@link RemoteIntelligenceService} to indicate the session was created (when {@code context}
- * is not {@code null} or destroyed (when {@code context} is {@code null}).
- */
- public void onSessionLifecycleRequest(@Nullable InteractionContext context,
- @NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send a batch of events to the service.
- */
- public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send snapshot data to the service.
- */
- public void onActivitySnapshotRequest(@NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to request augmented autofill.
- */
- public void onRequestAutofillLocked(@NonNull InteractionSessionId sessionId,
- @NonNull IAutoFillManagerClient client, int autofillSessionId,
- @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingAutofillRequest(this, sessionId, client, autofillSessionId,
- focusedId, focusedValue));
- }
-
- /**
- * Called by {@link ContentCaptureSession} when it's time to destroy all augmented autofill
- * requests.
- */
- public void onDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
- }
-
- private abstract static class MyPendingRequest
- extends PendingRequest<RemoteIntelligenceService> {
- protected final InteractionSessionId mSessionId;
-
- private MyPendingRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service);
- mSessionId = sessionId;
- }
-
- @Override // from PendingRequest
- protected final void onTimeout(RemoteIntelligenceService remoteService) {
- Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
- + mSessionId);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
- }
-
- @Override // from PendingRequest
- public final void run() {
- final RemoteIntelligenceService remoteService = getService();
- if (remoteService != null) {
- try {
- // We don't expect the service to call us back, so we finish right away.
- myRun(remoteService);
- // TODO(b/111330312): not true anymore!!
- finish();
- } catch (RemoteException e) {
- Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
- + mSessionId + ": " + e);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
- }
- }
- }
-
- protected abstract void myRun(@NonNull RemoteIntelligenceService service)
- throws RemoteException;
-
- }
-
- private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
-
- private final InteractionContext mContext;
-
- protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
- @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- mContext = context;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onSessionLifecycle(mContext, mSessionId);
- }
- }
-
- private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
-
- private final List<ContentCaptureEvent> mEvents;
-
- protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- super(service, sessionId);
- mEvents = events;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onContentCaptureEventsRequest(mSessionId,
- new ContentCaptureEventsRequest(mEvents));
- }
- }
-
- private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
-
- private final SnapshotData mSnapshotData;
-
- protected PendingOnActivitySnapshotRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- super(service, sessionId);
- mSnapshotData = snapshotData;
- }
-
- @Override // from MyPendingRequest
- protected void myRun(@NonNull RemoteIntelligenceService remoteService)
- throws RemoteException {
- remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
- }
- }
-
- private static final class PendingAutofillRequest extends MyPendingRequest {
- private final @NonNull AutofillId mFocusedId;
- private final @Nullable AutofillValue mFocusedValue;
- private final @NonNull IAutoFillManagerClient mClient;
- private final int mAutofillSessionId;
- private final long mRequestTime = SystemClock.elapsedRealtime();
-
- protected PendingAutofillRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId, @NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- super(service, sessionId);
- mClient = client;
- mAutofillSessionId = autofillSessionId;
- mFocusedId = focusedId;
- mFocusedValue = focusedValue;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- final IResultReceiver receiver = new IResultReceiver.Stub() {
-
- @Override
- public void send(int resultCode, Bundle resultData) throws RemoteException {
- final IBinder realClient = resultData
- .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
- remoteService.mService.onAutofillRequest(mSessionId, realClient,
- mAutofillSessionId, mFocusedId, mFocusedValue, mRequestTime);
- }
- };
-
- // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
- // cache IAugmentedAutofillManagerClient reference, etc...
- mClient.getAugmentedAutofillClient(receiver);
- }
- }
-
- private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
-
- protected PendingDestroyAutofillWindowsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- }
-
- @Override
- protected void myRun(@NonNull RemoteIntelligenceService service) throws RemoteException {
- service.mService.onDestroyAutofillWindowsRequest(mSessionId);
- // TODO(b/111330312): implement timeout
- }
- }
-
- public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
- // To keep it simple, we use the same callback for all failures / timeouts.
- void onFailureOrTimeout(boolean timedOut);
- }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c4d2a91..744d386 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -239,8 +239,8 @@
"com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
"com.android.server.autofill.AutofillManagerService";
- private static final String INTELLIGENCE_MANAGER_SERVICE_CLASS =
- "com.android.server.intelligence.IntelligenceManagerService";
+ private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
+ "com.android.server.contentcapture.ContentCaptureManagerService";
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
"com.android.server.timezone.RulesManagerService$Lifecycle";
private static final String IOT_SERVICE_CLASS =
@@ -1136,7 +1136,7 @@
traceEnd();
}
- startIntelligenceService(context);
+ startContentCaptureService(context);
// NOTE: ClipboardService indirectly depends on IntelligenceService
traceBeginAndSlog("StartClipboardService");
@@ -2100,18 +2100,18 @@
}, BOOT_TIMINGS_TRACE_LOG);
}
- private void startIntelligenceService(@NonNull Context context) {
+ private void startContentCaptureService(@NonNull Context context) {
// First check if it was explicitly enabled by Settings
boolean explicitlySupported = false;
final String settings = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED);
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED);
if (settings != null) {
explicitlySupported = Boolean.parseBoolean(settings);
if (explicitlySupported) {
- Slog.d(TAG, "IntelligenceService explicitly enabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly enabled by Settings");
} else {
- Slog.d(TAG, "IntelligenceService explicitly disabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly disabled by Settings");
return;
}
}
@@ -2119,15 +2119,15 @@
// Then check if OEM overlaid the resource that defines the service.
if (!explicitlySupported) {
final String serviceName = context
- .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService);
+ .getString(com.android.internal.R.string.config_defaultContentCaptureService);
if (TextUtils.isEmpty(serviceName)) {
- Slog.d(TAG, "IntelligenceService disabled because config resource is not overlaid");
+ Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
return;
}
}
- traceBeginAndSlog("StartIntelligenceService");
- mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+ traceBeginAndSlog("StartContentCaptureService");
+ mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
traceEnd();
}