diff options
11 files changed, 91 insertions, 205 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index d33b030c12d6..49bd885f2641 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3875,8 +3875,6 @@ package android.service.autofill { public abstract class AutofillFieldClassificationService extends android.app.Service { method public android.os.IBinder onBind(android.content.Intent); - method public java.util.List<java.lang.String> onGetAvailableAlgorithms(); - method public java.lang.String onGetDefaultAlgorithm(); method public android.service.autofill.AutofillFieldClassificationService.Scores onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService"; } diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java index 18f6dab9fc59..78e2bd1e667a 100644 --- a/core/java/android/service/autofill/AutofillFieldClassificationService.java +++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java @@ -15,9 +15,6 @@ */ package android.service.autofill; -import static android.view.autofill.AutofillManager.EXTRA_AVAILABLE_ALGORITHMS; -import static android.view.autofill.AutofillManager.EXTRA_DEFAULT_ALGORITHM; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -58,9 +55,7 @@ public abstract class AutofillFieldClassificationService extends Service { private static final String TAG = "AutofillFieldClassificationService"; - private static final int MSG_GET_AVAILABLE_ALGORITHMS = 1; - private static final int MSG_GET_DEFAULT_ALGORITHM = 2; - private static final int MSG_GET_SCORES = 3; + private static final int MSG_GET_SCORES = 1; /** * The {@link Intent} action that must be declared as handled by a service @@ -79,21 +74,6 @@ public abstract class AutofillFieldClassificationService extends Service { final Bundle data = new Bundle(); final RemoteCallback callback; switch (action) { - case MSG_GET_AVAILABLE_ALGORITHMS: - callback = (RemoteCallback) msg.obj; - final List<String> availableAlgorithms = onGetAvailableAlgorithms(); - String[] asArray = null; - if (availableAlgorithms != null) { - asArray = new String[availableAlgorithms.size()]; - availableAlgorithms.toArray(asArray); - } - data.putStringArray(EXTRA_AVAILABLE_ALGORITHMS, asArray); - break; - case MSG_GET_DEFAULT_ALGORITHM: - callback = (RemoteCallback) msg.obj; - final String defaultAlgorithm = onGetDefaultAlgorithm(); - data.putString(EXTRA_DEFAULT_ALGORITHM, defaultAlgorithm); - break; case MSG_GET_SCORES: final SomeArgs args = (SomeArgs) msg.obj; callback = (RemoteCallback) args.arg1; @@ -134,27 +114,6 @@ public abstract class AutofillFieldClassificationService extends Service { } /** - * Gets the name of all available algorithms. - * - * @throws UnsupportedOperationException if not implemented by service. - */ - // TODO(b/70939974): rename to onGetAvailableAlgorithms if not removed - @NonNull - public List<String> onGetAvailableAlgorithms() { - throw new UnsupportedOperationException("Must be implemented by external service"); - } - - /** - * Gets the default algorithm that's used when an algorithm is not specified or is invalid. - * - * @throws UnsupportedOperationException if not implemented by service. - */ - @NonNull - public String onGetDefaultAlgorithm() { - throw new UnsupportedOperationException("Must be implemented by external service"); - } - - /** * Calculates field classification scores in a batch. * * <p>See {@link AutofillFieldClassificationService} for more info about field classification @@ -179,17 +138,6 @@ public abstract class AutofillFieldClassificationService extends Service { private final class AutofillFieldClassificationServiceWrapper extends IAutofillFieldClassificationService.Stub { - - @Override - public void getAvailableAlgorithms(RemoteCallback callback) throws RemoteException { - mHandlerCaller.obtainMessageO(MSG_GET_AVAILABLE_ALGORITHMS, callback).sendToTarget(); - } - - @Override - public void getDefaultAlgorithm(RemoteCallback callback) throws RemoteException { - mHandlerCaller.obtainMessageO(MSG_GET_DEFAULT_ALGORITHM, callback).sendToTarget(); - } - @Override public void getScores(RemoteCallback callback, String algorithmName, Bundle algorithmArgs, List<AutofillValue> actualValues, String[] userDataValues) diff --git a/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl index d8e829d8f67c..398557d5ad2e 100644 --- a/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl +++ b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl @@ -27,8 +27,6 @@ import java.util.List; * @hide */ oneway interface IAutofillFieldClassificationService { - void getAvailableAlgorithms(in RemoteCallback callback); - void getDefaultAlgorithm(in RemoteCallback callback); void getScores(in RemoteCallback callback, String algorithmName, in Bundle algorithmArgs, - in List<AutofillValue> actualValues, in String[] userDataValues); + in List<AutofillValue> actualValues, in String[] userDataValues); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index f54561bfb423..4b24a71c8bfb 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -33,7 +33,6 @@ import android.metrics.LogMaker; import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; -import android.os.RemoteCallback; import android.os.RemoteException; import android.service.autofill.AutofillService; import android.service.autofill.FillEventHistory; @@ -58,8 +57,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; // TODO: use java.lang.ref.Cleaner once Android supports Java 9 import sun.misc.Cleaner; @@ -177,11 +174,6 @@ public final class AutofillManager { public static final String EXTRA_RESTORE_SESSION_TOKEN = "android.view.autofill.extra.RESTORE_SESSION_TOKEN"; - /** @hide */ - public static final String EXTRA_AVAILABLE_ALGORITHMS = "available_algorithms"; - /** @hide */ - public static final String EXTRA_DEFAULT_ALGORITHM = "default_algorithm"; - private static final String SESSION_ID_TAG = "android:sessionId"; private static final String STATE_TAG = "android:state"; private static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; @@ -1174,22 +1166,10 @@ public final class AutofillManager { * and it's ignored if the caller currently doesn't have an enabled autofill service for * the user. */ - // TODO(b/70939974): refactor this method to be "purely" sync by getting the info from the - // the ExtService manifest (instead of calling the service) @Nullable public String getDefaultFieldClassificationAlgorithm() { - final SyncRemoteCallbackListener<String> listener = - new SyncRemoteCallbackListener<String>() { - - @Override - String getResult(Bundle result) { - return result == null ? null : result.getString(EXTRA_DEFAULT_ALGORITHM); - } - }; - try { - mService.getDefaultFieldClassificationAlgorithm(new RemoteCallback(listener)); - return listener.getResult(FC_SERVICE_TIMEOUT); + return mService.getDefaultFieldClassificationAlgorithm(); } catch (RemoteException e) { e.rethrowFromSystemServer(); return null; @@ -1204,29 +1184,12 @@ public final class AutofillManager { * and it returns an empty list if the caller currently doesn't have an enabled autofill service * for the user. */ - // TODO(b/70939974): refactor this method to be "purely" sync by getting the info from the - // the ExtService manifest (instead of calling the service) @NonNull public List<String> getAvailableFieldClassificationAlgorithms() { - final SyncRemoteCallbackListener<List<String>> listener = - new SyncRemoteCallbackListener<List<String>>() { - - @Override - List<String> getResult(Bundle result) { - List<String> algorithms = null; - if (result != null) { - final String[] asArray = result.getStringArray(EXTRA_AVAILABLE_ALGORITHMS); - if (asArray != null) { - algorithms = Arrays.asList(asArray); - } - } - return algorithms != null ? algorithms : Collections.emptyList(); - } - }; - + final String[] algorithms; try { - mService.getAvailableFieldClassificationAlgorithms(new RemoteCallback(listener)); - return listener.getResult(FC_SERVICE_TIMEOUT); + algorithms = mService.getAvailableFieldClassificationAlgorithms(); + return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList(); } catch (RemoteException e) { e.rethrowFromSystemServer(); return null; @@ -2322,36 +2285,4 @@ public final class AutofillManager { } } } - - private abstract static class SyncRemoteCallbackListener<T> - implements RemoteCallback.OnResultListener { - - private final CountDownLatch mLatch = new CountDownLatch(1); - private T mResult; - - @Override - public void onResult(Bundle result) { - if (sVerbose) Log.w(TAG, "SyncRemoteCallbackListener.onResult(): " + result); - mResult = getResult(result); - mLatch.countDown(); - } - - T getResult(int timeoutMs) { - T result = null; - try { - if (mLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) { - result = mResult; - } else { - Log.w(TAG, "SyncRemoteCallbackListener not called in " + timeoutMs + "ms"); - } - } catch (InterruptedException e) { - Log.w(TAG, "SyncRemoteCallbackListener interrupted: " + e); - Thread.currentThread().interrupt(); - } - if (sVerbose) Log.w(TAG, "SyncRemoteCallbackListener: returning " + result); - return result; - } - - abstract T getResult(Bundle result); - } } diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 41672e7aeb9b..1a11fbba0011 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -59,6 +59,6 @@ interface IAutoFillManager { void setUserData(in UserData userData); boolean isFieldClassificationEnabled(); ComponentName getAutofillServiceComponentName(); - void getAvailableFieldClassificationAlgorithms(in RemoteCallback callback); - void getDefaultFieldClassificationAlgorithm(in RemoteCallback callback); + String[] getAvailableFieldClassificationAlgorithms(); + String getDefaultFieldClassificationAlgorithm(); } diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml index 63d3623c468a..45e557c00333 100644 --- a/packages/ExtServices/AndroidManifest.xml +++ b/packages/ExtServices/AndroidManifest.xml @@ -56,6 +56,12 @@ <intent-filter> <action android:name="android.service.autofill.AutofillFieldClassificationService" /> </intent-filter> + <meta-data + android:name="android.autofill.field_classification.default_algorithm" + android:resource="@string/autofill_field_classification_default_algorithm" /> + <meta-data + android:name="android.autofill.field_classification.available_algorithms" + android:resource="@array/autofill_field_classification_available_algorithms" /> </service> <library android:name="android.ext.services"/> diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml index a2e65bc8f9fd..72647ab8ae3f 100644 --- a/packages/ExtServices/res/values/strings.xml +++ b/packages/ExtServices/res/values/strings.xml @@ -19,4 +19,9 @@ <string name="notification_assistant">Notification Assistant</string> <string name="prompt_block_reason">Too many dismissals:views</string> + + <string name="autofill_field_classification_default_algorithm">EDIT_DISTANCE</string> + <string-array name="autofill_field_classification_available_algorithms"> + <item>EDIT_DISTANCE</item> + </string-array> </resources> diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java index ea516a1db8b8..068ff8b4c5ae 100644 --- a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java +++ b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java @@ -24,24 +24,13 @@ import android.view.autofill.AutofillValue; import com.android.internal.util.ArrayUtils; -import java.util.Arrays; import java.util.List; public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService { private static final String TAG = "AutofillFieldClassificationServiceImpl"; - private static final boolean DEBUG = false; - private static final List<String> sAvailableAlgorithms = Arrays.asList(EditDistanceScorer.NAME); - - @Override - public List<String> onGetAvailableAlgorithms() { - return sAvailableAlgorithms; - } - - @Override - public String onGetDefaultAlgorithm() { - return EditDistanceScorer.NAME; - } + // TODO(b/70291841): set to false before launching + private static final boolean DEBUG = true; @Nullable @Override diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 6d845f9a9d3a..c0628005d410 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -646,37 +646,35 @@ public final class AutofillManagerService extends SystemService { } @Override - public void getDefaultFieldClassificationAlgorithm(RemoteCallback callback) - throws RemoteException { + public String getDefaultFieldClassificationAlgorithm() throws RemoteException { final int userId = UserHandle.getCallingUserId(); synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service != null) { - service.getDefaultFieldClassificationAlgorithm(getCallingUid(), callback); + return service.getDefaultFieldClassificationAlgorithm(getCallingUid()); } else { if (sVerbose) { Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId); } - callback.sendResult(null); - } + return null; + } } } @Override - public void getAvailableFieldClassificationAlgorithms(RemoteCallback callback) - throws RemoteException { + public String[] getAvailableFieldClassificationAlgorithms() throws RemoteException { final int userId = UserHandle.getCallingUserId(); synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service != null) { - service.getAvailableFieldClassificationAlgorithms(getCallingUid(), callback); + return service.getAvailableFieldClassificationAlgorithms(getCallingUid()); } else { if (sVerbose) { Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId); } - callback.sendResult(null); + return null; } } } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index a5bd59a9e77d..6bcfc4bf5a5e 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -1153,22 +1153,22 @@ final class AutofillManagerServiceImpl { return mFieldClassificationStrategy; } - void getAvailableFieldClassificationAlgorithms(int callingUid, RemoteCallback callback) { + String[] getAvailableFieldClassificationAlgorithms(int callingUid) { synchronized (mLock) { if (!isCalledByServiceLocked("getFCAlgorithms()", callingUid)) { - return; + return null; } } - mFieldClassificationStrategy.getAvailableAlgorithms(callback); + return mFieldClassificationStrategy.getAvailableAlgorithms(); } - void getDefaultFieldClassificationAlgorithm(int callingUid, RemoteCallback callback) { + String getDefaultFieldClassificationAlgorithm(int callingUid) { synchronized (mLock) { if (!isCalledByServiceLocked("getDefaultFCAlgorithm()", callingUid)) { - return; + return null; } } - mFieldClassificationStrategy.getDefaultAlgorithm(callback); + return mFieldClassificationStrategy.getDefaultAlgorithm(); } @Override diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java index 7228f1d2a8ea..594032adb4b5 100644 --- a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java +++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java @@ -15,8 +15,6 @@ */ package com.android.server.autofill; -import static android.view.autofill.AutofillManager.EXTRA_AVAILABLE_ALGORITHMS; -import static android.view.autofill.AutofillManager.EXTRA_DEFAULT_ALGORITHM; import static android.view.autofill.AutofillManager.FC_SERVICE_TIMEOUT; import static com.android.server.autofill.Helper.sDebug; @@ -33,6 +31,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -49,6 +48,7 @@ import com.android.internal.annotations.GuardedBy; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -62,6 +62,11 @@ final class FieldClassificationStrategy { private static final String TAG = "FieldClassificationStrategy"; + private static final String METADATA_KEY_DEFAULT_ALGORITHM = + "android.autofill.field_classification.default_algorithm"; + private static final String METADATA_KEY_AVAILABLE_ALGORITHMS = + "android.autofill.field_classification.available_algorithms"; + private final Context mContext; private final Object mLock = new Object(); private final int mUserId; @@ -80,7 +85,8 @@ final class FieldClassificationStrategy { mUserId = userId; } - private ComponentName getServiceComponentName() { + @Nullable + private ServiceInfo getServiceInfo() { final String packageName = mContext.getPackageManager().getServicesSystemSharedLibraryPackageName(); if (packageName == null) { @@ -96,9 +102,15 @@ final class FieldClassificationStrategy { Slog.w(TAG, "No valid components found."); return null; } - final ServiceInfo serviceInfo = resolveInfo.serviceInfo; - final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name); + return resolveInfo.serviceInfo; + } + @Nullable + private ComponentName getServiceComponentName() { + final ServiceInfo serviceInfo = getServiceInfo(); + if (serviceInfo == null) return null; + + final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name); if (!Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE .equals(serviceInfo.permission)) { Slog.w(TAG, name.flattenToShortString() + " does not require permission " @@ -204,12 +216,40 @@ final class FieldClassificationStrategy { } } - void getAvailableAlgorithms(RemoteCallback callback) { - connectAndRun((service) -> service.getAvailableAlgorithms(callback)); + /** + * Gets the name of all available algorithms. + */ + @Nullable + String[] getAvailableAlgorithms() { + return getMetadataValue(METADATA_KEY_AVAILABLE_ALGORITHMS, + (res, id) -> res.getStringArray(id)); + } + + /** + * Gets the default algorithm that's used when an algorithm is not specified or is invalid. + */ + @Nullable + String getDefaultAlgorithm() { + return getMetadataValue(METADATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id)); } - void getDefaultAlgorithm(RemoteCallback callback) { - connectAndRun((service) -> service.getDefaultAlgorithm(callback)); + @Nullable + private <T> T getMetadataValue(String field, MetadataParser<T> parser) { + final ServiceInfo serviceInfo = getServiceInfo(); + if (serviceInfo == null) return null; + + final PackageManager pm = mContext.getPackageManager(); + + final Resources res; + try { + res = pm.getResourcesForApplication(serviceInfo.applicationInfo); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Error getting application resources for " + serviceInfo, e); + return null; + } + + final int resourceId = serviceInfo.metaData.getInt(field); + return parser.get(res, resourceId); } //TODO(b/70291841): rename this method (and all others in the chain) to something like @@ -237,43 +277,16 @@ final class FieldClassificationStrategy { } pw.println(impl.flattenToShortString()); - final CountDownLatch latch = new CountDownLatch(2); - - // Lock used to make sure lines don't overlap - final Object lock = latch; - - connectAndRun((service) -> service.getAvailableAlgorithms(new RemoteCallback((bundle) -> { - synchronized (lock) { - pw.print(prefix); pw.print("Available algorithms: "); - pw.println(bundle.getStringArrayList(EXTRA_AVAILABLE_ALGORITHMS)); - } - latch.countDown(); - }))); - - connectAndRun((service) -> service.getDefaultAlgorithm(new RemoteCallback((bundle) -> { - synchronized (lock) { - pw.print(prefix); pw.print("Default algorithm: "); - pw.println(bundle.getString(EXTRA_DEFAULT_ALGORITHM)); - } - latch.countDown(); - }))); - - try { - if (!latch.await(FC_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS)) { - synchronized (lock) { - pw.print(prefix); pw.print("timeout ("); pw.print(FC_SERVICE_TIMEOUT); - pw.println("ms) waiting for service"); - } - } - } catch (InterruptedException e) { - synchronized (lock) { - pw.print(prefix); pw.println("interrupted while waiting for service"); - } - Thread.currentThread().interrupt(); - } + pw.print(prefix); pw.print("Available algorithms: "); + pw.println(Arrays.toString(getAvailableAlgorithms())); + pw.print(prefix); pw.print("Default algorithm: "); pw.println(getDefaultAlgorithm()); } - private interface Command { + private static interface Command { void run(IAutofillFieldClassificationService service) throws RemoteException; } + + private static interface MetadataParser<T> { + T get(Resources res, int resId); + } } |