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

Commit 50a637b1 authored by Adam He's avatar Adam He
Browse files

Changed createOnDeviceTranslator to be asynchronous with callback.

Bug: 176208267
Test: atest CtsTranslationTestCases
Change-Id: Icedc953611e70dc208cbef54b4e459ebb0ccd5a9
parent 8a170b2e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -52839,7 +52839,8 @@ package android.view.translation {
    method public void addOnDeviceTranslationCapabilityUpdateListener(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.translation.TranslationCapability>);
    method @Deprecated public void addOnDeviceTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
    method @Deprecated public void addTranslationCapabilityUpdateListener(int, int, @NonNull android.app.PendingIntent);
    method @Nullable @WorkerThread public android.view.translation.Translator createOnDeviceTranslator(@NonNull android.view.translation.TranslationContext);
    method public void createOnDeviceTranslator(@NonNull android.view.translation.TranslationContext, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.translation.Translator>);
    method @Deprecated @Nullable @WorkerThread public android.view.translation.Translator createOnDeviceTranslator(@NonNull android.view.translation.TranslationContext);
    method @Deprecated @Nullable @WorkerThread public android.view.translation.Translator createTranslator(@NonNull android.view.translation.TranslationContext);
    method @NonNull @WorkerThread public java.util.Set<android.view.translation.TranslationCapability> getOnDeviceTranslationCapabilities(int, int);
    method @Nullable public android.app.PendingIntent getOnDeviceTranslationSettingsActivityIntent();
+61 −4
Original line number Diff line number Diff line
@@ -100,10 +100,6 @@ public final class TranslationManager {

    private final ITranslationManager mService;

    @Nullable
    @GuardedBy("mLock")
    private ITranslationDirectManager mDirectServiceBinder;

    @NonNull
    @GuardedBy("mLock")
    private final SparseArray<Translator> mTranslators = new SparseArray<>();
@@ -128,14 +124,75 @@ public final class TranslationManager {
        mHandler = Handler.createAsync(Looper.getMainLooper());
    }

    /**
     * Creates an on-device Translator for natural language translation.
     *
     * @param translationContext {@link TranslationContext} containing the specs for creating the
     *                                                     Translator.
     * @param executor Executor to run callback operations
     * @param callback {@link Consumer} to receive the translator. A {@code null} value is returned
     *                                 if the service could not create the translator.
     */
    public void createOnDeviceTranslator(@NonNull TranslationContext translationContext,
            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Translator> callback) {
        Objects.requireNonNull(translationContext, "translationContext cannot be null");
        Objects.requireNonNull(executor, "executor cannot be null");
        Objects.requireNonNull(callback, "callback cannot be null");

        synchronized (mLock) {
            // TODO(b/176464808): Disallow multiple Translator now, it will throw
            //  IllegalStateException. Need to discuss if we can allow multiple Translators.
            if (mTranslatorIds.containsKey(translationContext)) {
                executor.execute(() -> callback.accept(
                        mTranslators.get(mTranslatorIds.get(translationContext))));
                return;
            }

            int translatorId;
            do {
                translatorId = Math.abs(ID_GENERATOR.nextInt());
            } while (translatorId == 0 || mTranslators.indexOfKey(translatorId) >= 0);
            final int tId = translatorId;

            new Translator(mContext, translationContext, translatorId, this, mHandler, mService,
                    new Consumer<Translator>() {
                        @Override
                        public void accept(Translator translator) {
                            if (translator == null) {
                                final long token = Binder.clearCallingIdentity();
                                try {
                                    executor.execute(() -> callback.accept(null));
                                } finally {
                                    Binder.restoreCallingIdentity(token);
                                }
                                return;
                            }

                            mTranslators.put(tId, translator);
                            mTranslatorIds.put(translationContext, tId);
                            final long token = Binder.clearCallingIdentity();
                            try {
                                executor.execute(() -> callback.accept(translator));
                            } finally {
                                Binder.restoreCallingIdentity(token);
                            }
                        }
                    });
        }
    }

    /**
     * Creates an on-device Translator for natural language translation.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * @deprecated use {@link #createOnDeviceTranslator(TranslationContext, Executor, Consumer)}
     * instead.
     *
     * @param translationContext {@link TranslationContext} containing the specs for creating the
     *                                                     Translator.
     */
    @Deprecated
    @Nullable
    @WorkerThread
    public Translator createOnDeviceTranslator(@NonNull TranslationContext translationContext) {
+40 −0
Original line number Diff line number Diff line
@@ -101,10 +101,18 @@ public class Translator {
    public static final String EXTRA_SESSION_ID = "sessionId";

    static class ServiceBinderReceiver extends IResultReceiver.Stub {
        // TODO: refactor how translator is instantiated after removing deprecated createTranslator.
        private final WeakReference<Translator> mTranslator;
        private final CountDownLatch mLatch = new CountDownLatch(1);
        private int mSessionId;

        private Consumer<Translator> mCallback;

        ServiceBinderReceiver(Translator translator, Consumer<Translator> callback) {
            mTranslator = new WeakReference<>(translator);
            mCallback = callback;
        }

        ServiceBinderReceiver(Translator translator) {
            mTranslator = new WeakReference<>(translator);
        }
@@ -126,6 +134,9 @@ public class Translator {
        public void send(int resultCode, Bundle resultData) {
            if (resultCode == STATUS_SYNC_CALL_FAIL) {
                mLatch.countDown();
                if (mCallback != null) {
                    mCallback.accept(null);
                }
                return;
            }
            mSessionId = resultData.getInt(EXTRA_SESSION_ID);
@@ -146,6 +157,9 @@ public class Translator {
            }
            translator.setServiceBinder(binder);
            mLatch.countDown();
            if (mCallback != null) {
                mCallback.accept(translator);
            }
        }

        // TODO(b/176464808): maybe make SyncResultReceiver.TimeoutException constructor public
@@ -157,6 +171,32 @@ public class Translator {
        }
    }

    /**
     * Create the Translator.
     *
     * @hide
     */
    public Translator(@NonNull Context context,
            @NonNull TranslationContext translationContext, int sessionId,
            @NonNull TranslationManager translationManager, @NonNull Handler handler,
            @Nullable ITranslationManager systemServerBinder,
            @NonNull Consumer<Translator> callback) {
        mContext = context;
        mTranslationContext = translationContext;
        mId = sessionId;
        mManager = translationManager;
        mHandler = handler;
        mSystemServerBinder = systemServerBinder;
        mServiceBinderReceiver = new ServiceBinderReceiver(this, callback);

        try {
            mSystemServerBinder.onSessionCreated(mTranslationContext, mId,
                    mServiceBinderReceiver, mContext.getUserId());
        } catch (RemoteException e) {
            Log.w(TAG, "RemoteException calling startSession(): " + e);
        }
    }

    /**
     * Create the Translator.
     *