Implemented getAlgorithm() and getDefaultAlgorithm() using manifest metadata.
Bug: 70939974 Test: atest CtsAutoFillServiceTestCases:FieldsClassificationTest Change-Id: I8b7028c0acfef164b84821a9e4c99817acc838f8
This commit is contained in:
@@ -3862,8 +3862,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";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -133,27 +113,6 @@ public abstract class AutofillFieldClassificationService extends Service {
|
||||
return mWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
void getDefaultAlgorithm(RemoteCallback callback) {
|
||||
connectAndRun((service) -> service.getDefaultAlgorithm(callback));
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user