Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4e52285 authored by Felipe Leme's avatar Felipe Leme
Browse files

Make IAutofillManager fully oneway.

The critical methods on this interface - like updateSession() - were already
void, so all we had to do were to "onewaywize" the other methods. We could
either refactor them to be truly async, or implement a blocking mechanism that
let them still be sync *and* oneway - because these methods are not in the
critical path, we opted for the latter, which is simpler and less risky.

Fixes: 73536867

Test: mmma -j ./frameworks/base/apct-tests/perftests/autofill/ && \
      adb install -r $OUT/data/app/AutofillPerfTests/AutofillPerfTests.apk && \
      adb shell am instrument -w -e class android.view.autofill.LoginTest \
      com.android.perftests.autofill/android.support.test.runner.AndroidJUnitRunner
Test: CtsAutoFillServiceTestCases

Change-Id: I380430aa2a7805aed6f629afb360566fc5402abb
parent d955be72
Loading
Loading
Loading
Loading
+141 −16
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ import android.view.accessibility.AccessibilityWindowInfo;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;


@@ -72,6 +73,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Objects;
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
//TODO: use java.lang.ref.Cleaner once Android supports Java 9
import sun.misc.Cleaner;
import sun.misc.Cleaner;
@@ -572,10 +575,11 @@ public final class AutofillManager {


                final AutofillClient client = getClient();
                final AutofillClient client = getClient();
                if (client != null) {
                if (client != null) {
                    final SyncResultReceiver receiver = new SyncResultReceiver();
                    try {
                    try {
                        final boolean sessionWasRestored = mService.restoreSession(mSessionId,
                        mService.restoreSession(mSessionId, client.autofillClientGetActivityToken(),
                                client.autofillClientGetActivityToken(),
                                mServiceClient.asBinder(), receiver);
                                mServiceClient.asBinder());
                        final boolean sessionWasRestored = receiver.getIntResult() == 1;


                        if (!sessionWasRestored) {
                        if (!sessionWasRestored) {
                            Log.w(TAG, "Session " + mSessionId + " could not be restored");
                            Log.w(TAG, "Session " + mSessionId + " could not be restored");
@@ -691,7 +695,9 @@ public final class AutofillManager {
     */
     */
    @Nullable public FillEventHistory getFillEventHistory() {
    @Nullable public FillEventHistory getFillEventHistory() {
        try {
        try {
            return mService.getFillEventHistory();
            final SyncResultReceiver receiver = new SyncResultReceiver();
            mService.getFillEventHistory(receiver);
            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
            return null;
            return null;
@@ -1242,8 +1248,10 @@ public final class AutofillManager {
    public boolean hasEnabledAutofillServices() {
    public boolean hasEnabledAutofillServices() {
        if (mService == null) return false;
        if (mService == null) return false;


        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            return mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName());
            mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName(), receiver);
            return receiver.getIntResult() == 1;
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
@@ -1257,8 +1265,10 @@ public final class AutofillManager {
    public ComponentName getAutofillServiceComponentName() {
    public ComponentName getAutofillServiceComponentName() {
        if (mService == null) return null;
        if (mService == null) return null;


        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            return mService.getAutofillServiceComponentName();
            mService.getAutofillServiceComponentName(receiver);
            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
@@ -1281,7 +1291,9 @@ public final class AutofillManager {
     */
     */
    @Nullable public String getUserDataId() {
    @Nullable public String getUserDataId() {
        try {
        try {
            return mService.getUserDataId();
            final SyncResultReceiver receiver = new SyncResultReceiver();
            mService.getUserDataId(receiver);
            return receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
            return null;
            return null;
@@ -1301,7 +1313,9 @@ public final class AutofillManager {
     */
     */
    @Nullable public UserData getUserData() {
    @Nullable public UserData getUserData() {
        try {
        try {
            return mService.getUserData();
            final SyncResultReceiver receiver = new SyncResultReceiver();
            mService.getUserData(receiver);
            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
            return null;
            return null;
@@ -1337,8 +1351,10 @@ public final class AutofillManager {
     * the user.
     * the user.
     */
     */
    public boolean isFieldClassificationEnabled() {
    public boolean isFieldClassificationEnabled() {
        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            return mService.isFieldClassificationEnabled();
            mService.isFieldClassificationEnabled(receiver);
            return receiver.getIntResult() == 1;
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
            return false;
            return false;
@@ -1358,8 +1374,10 @@ public final class AutofillManager {
     */
     */
    @Nullable
    @Nullable
    public String getDefaultFieldClassificationAlgorithm() {
    public String getDefaultFieldClassificationAlgorithm() {
        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            return mService.getDefaultFieldClassificationAlgorithm();
            mService.getDefaultFieldClassificationAlgorithm(receiver);
            return receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
            return null;
            return null;
@@ -1376,9 +1394,10 @@ public final class AutofillManager {
     */
     */
    @NonNull
    @NonNull
    public List<String> getAvailableFieldClassificationAlgorithms() {
    public List<String> getAvailableFieldClassificationAlgorithms() {
        final String[] algorithms;
        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            algorithms = mService.getAvailableFieldClassificationAlgorithms();
            mService.getAvailableFieldClassificationAlgorithms(receiver);
            final String[] algorithms = receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
            return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
            return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
@@ -1399,8 +1418,10 @@ public final class AutofillManager {
    public boolean isAutofillSupported() {
    public boolean isAutofillSupported() {
        if (mService == null) return false;
        if (mService == null) return false;


        final SyncResultReceiver receiver = new SyncResultReceiver();
        try {
        try {
            return mService.isServiceSupported(mContext.getUserId());
            mService.isServiceSupported(mContext.getUserId(), receiver);
            return receiver.getIntResult() == 1;
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
@@ -1521,10 +1542,12 @@ public final class AutofillManager {
            final AutofillClient client = getClient();
            final AutofillClient client = getClient();
            if (client == null) return; // NOTE: getClient() already logged it..
            if (client == null) return; // NOTE: getClient() already logged it..


            mSessionId = mService.startSession(client.autofillClientGetActivityToken(),
            final SyncResultReceiver receiver = new SyncResultReceiver();
            mService.startSession(client.autofillClientGetActivityToken(),
                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                    mCallback != null, flags, client.autofillClientGetComponentName(),
                    mCallback != null, flags, client.autofillClientGetComponentName(),
                    isCompatibilityModeEnabledLocked());
                    isCompatibilityModeEnabledLocked(), receiver);
            mSessionId = receiver.getIntResult();
            if (mSessionId != NO_SESSION) {
            if (mSessionId != NO_SESSION) {
                mState = STATE_ACTIVE;
                mState = STATE_ACTIVE;
            }
            }
@@ -1602,7 +1625,9 @@ public final class AutofillManager {
            mServiceClient = new AutofillManagerClient(this);
            mServiceClient = new AutofillManagerClient(this);
            try {
            try {
                final int userId = mContext.getUserId();
                final int userId = mContext.getUserId();
                final int flags = mService.addClient(mServiceClient, userId);
                final SyncResultReceiver receiver = new SyncResultReceiver();
                mService.addClient(mServiceClient, userId, receiver);
                final int flags = receiver.getIntResult();
                mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0;
                mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0;
                sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0;
                sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0;
                sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0;
                sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0;
@@ -2818,4 +2843,104 @@ public final class AutofillManager {
            }
            }
        }
        }
    }
    }

    /**
     * @hide
     */
    public static final class SyncResultReceiver extends IResultReceiver.Stub {

        private static final String EXTRA = "EXTRA";

        /**
         * How long to block waiting for {@link IResultReceiver} callbacks when calling server.
         */
        private static final long BINDER_TIMEOUT_MS = 5000;

        private static final int TYPE_STRING = 0;
        private static final int TYPE_STRING_ARRAY = 1;
        private static final int TYPE_PARCELABLE = 2;

        private final CountDownLatch mLatch  = new CountDownLatch(1);
        private int mResult;
        private Bundle mBundle;

        private void waitResult() {
            try {
                if (!mLatch.await(BINDER_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    throw new IllegalStateException("Not called in " + BINDER_TIMEOUT_MS + "ms");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        /**
         * Gets the result from an operation that returns an {@code int}.
         */
        int getIntResult() {
            waitResult();
            return mResult;
        }

        /**
         * Gets the result from an operation that returns an {@code Object}.
         *
         * @param type type of expected object.
         */
        @Nullable
        @SuppressWarnings("unchecked")
        <T> T getObjectResult(int type) {
            waitResult();
            if (mBundle == null) {
                return null;
            }
            switch (type) {
                case TYPE_STRING:
                    return (T) mBundle.getString(EXTRA);
                case TYPE_STRING_ARRAY:
                    return (T) mBundle.getString(EXTRA);
                case TYPE_PARCELABLE:
                    return (T) mBundle.getParcelable(EXTRA);
                default:
                    throw new IllegalArgumentException("unsupported type: " + type);
            }
        }

        @Override
        public void send(int resultCode, Bundle resultData) {
            mResult = resultCode;
            mBundle = resultData;
            mLatch.countDown();
        }

        /**
         * Creates a bundle for a {@code String} value.
         */
        @NonNull
        public static Bundle bundleFor(@Nullable String value) {
            final Bundle bundle = new Bundle();
            bundle.putString(EXTRA, value);
            return bundle;
        }

        /**
         * Creates a bundle for a {@code String[]} value.
         */
        @NonNull
        public static Bundle bundleFor(@Nullable String[] value) {
            final Bundle bundle = new Bundle();
            bundle.putStringArray(EXTRA, value);
            return bundle;
        }

        /**
         * Creates a bundle for a {@code Parcelable} value.
         */
        @NonNull
        public static Bundle bundleFor(@Nullable Parcelable value) {
            final Bundle bundle = new Bundle();
            bundle.putParcelable(EXTRA, value);
            return bundle;
        }
    }
}
}
+24 −26
Original line number Original line Diff line number Diff line
@@ -28,41 +28,39 @@ import android.service.autofill.UserData;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
import android.view.autofill.IAutoFillManagerClient;
import com.android.internal.os.IResultReceiver;


/**
/**
 * Mediator between apps being auto-filled and auto-fill service implementations.
 * Mediator between apps being auto-filled and auto-fill service implementations.
 *
 *
 * {@hide}
 * {@hide}
 */
 */
 // TODO(b/73536867) STOPSHIP : this whole interface should be either oneway or not, and we're
oneway interface IAutoFillManager {
 // gradually converting the methods (as some of them return a value form the server and must be
 // refactored).
interface IAutoFillManager {
    // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
    // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
    int addClient(in IAutoFillManagerClient client, int userId);
    void addClient(in IAutoFillManagerClient client, int userId, in IResultReceiver result);
    void removeClient(in IAutoFillManagerClient client, int userId);
    void removeClient(in IAutoFillManagerClient client, int userId);
    int startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
    void startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
        in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
        in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
            in ComponentName componentName, boolean compatMode);
        in ComponentName componentName, boolean compatMode, in IResultReceiver result);
    FillEventHistory getFillEventHistory();
    void getFillEventHistory(in IResultReceiver result);
    boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
    void restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback,
    oneway void updateSession(int sessionId, in AutofillId id, in Rect bounds,
        in IResultReceiver result);
    void updateSession(int sessionId, in AutofillId id, in Rect bounds,
        in AutofillValue value, int action, int flags, int userId);
        in AutofillValue value, int action, int flags, int userId);
    oneway void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId);
    void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId);
    oneway void finishSession(int sessionId, int userId);
    void finishSession(int sessionId, int userId);
    oneway void cancelSession(int sessionId, int userId);
    void cancelSession(int sessionId, int userId);
    oneway void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId,
    void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
            int userId);
    void setHasCallback(int sessionId, int userId, boolean hasIt);
    oneway void setHasCallback(int sessionId, int userId, boolean hasIt);
    void disableOwnedAutofillServices(int userId);
    void disableOwnedAutofillServices(int userId);
    boolean isServiceSupported(int userId);
    void isServiceSupported(int userId, in IResultReceiver result);
    boolean isServiceEnabled(int userId, String packageName);
    void isServiceEnabled(int userId, String packageName, in IResultReceiver result);
    void onPendingSaveUi(int operation, IBinder token);
    void onPendingSaveUi(int operation, IBinder token);
    UserData getUserData();
    void getUserData(in IResultReceiver result);
    String getUserDataId();
    void getUserDataId(in IResultReceiver result);
    void setUserData(in UserData userData);
    void setUserData(in UserData userData);
    boolean isFieldClassificationEnabled();
    void isFieldClassificationEnabled(in IResultReceiver result);
    ComponentName getAutofillServiceComponentName();
    void getAutofillServiceComponentName(in IResultReceiver result);
    String[] getAvailableFieldClassificationAlgorithms();
    void getAvailableFieldClassificationAlgorithms(in IResultReceiver result);
    String getDefaultFieldClassificationAlgorithm();
    void getDefaultFieldClassificationAlgorithm(in IResultReceiver result);
}
}
+89 −42

File changed.

Preview size limit exceeded, changes collapsed.