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

Commit bfba432f authored by Mark Punzalan's avatar Mark Punzalan Committed by Automerger Merge Worker
Browse files

Merge "Add package name to all UiTranslationStateCallback methods." into tm-dev am: dc59b878

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17262916

Change-Id: Ib173b4be60ccb6fbeabf00e3ec050db1a7e2fcea
parents 1bd0a653 dc59b878
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -54141,9 +54141,13 @@ package android.view.translation {
  public interface UiTranslationStateCallback {
  public interface UiTranslationStateCallback {
    method public void onFinished();
    method public void onFinished();
    method public default void onFinished(@NonNull String);
    method public void onPaused();
    method public void onPaused();
    method public default void onPaused(@NonNull String);
    method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
    method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
    method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale, @NonNull String);
    method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
    method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
    method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale, @NonNull String);
  }
  }
  @UiThread public interface ViewTranslationCallback {
  @UiThread public interface ViewTranslationCallback {
+18 −16
Original line number Original line Diff line number Diff line
@@ -101,33 +101,32 @@ public final class UiTranslationManager {
    public static final String LOG_TAG = "UiTranslation";
    public static final String LOG_TAG = "UiTranslation";


    /**
    /**
     * The state caller request to disable utranslation,, it is no longer need to ui translation.
     * The state the caller requests to enable UI translation.
     *
     *
     * @hide
     * @hide
     */
     */
    public static final int STATE_UI_TRANSLATION_STARTED = 0;
    public static final int STATE_UI_TRANSLATION_STARTED = 0;
    /**
    /**
     * The state caller request to pause ui translation, it will switch back to the original text.
     * The state caller requests to pause UI translation. It will switch back to the original text.
     *
     *
     * @hide
     * @hide
     */
     */
    public static final int STATE_UI_TRANSLATION_PAUSED = 1;
    public static final int STATE_UI_TRANSLATION_PAUSED = 1;
    /**
    /**
     * The state caller request to resume the paused ui translation, it will show the translated
     * The state caller requests to resume the paused UI translation. It will show the translated
     * text again if the text had been translated.
     * text again if the text had been translated.
     *
     *
     * @hide
     * @hide
     */
     */
    public static final int STATE_UI_TRANSLATION_RESUMED = 2;
    public static final int STATE_UI_TRANSLATION_RESUMED = 2;
    /**
    /**
     * The state the caller request to enable ui translation.
     * The state caller requests to disable UI translation when it no longer needs translation.
     *
     *
     * @hide
     * @hide
     */
     */
    public static final int STATE_UI_TRANSLATION_FINISHED = 3;
    public static final int STATE_UI_TRANSLATION_FINISHED = 3;
    /**

     * @hide
    /** @hide */
     */
    @IntDef(prefix = {"STATE__TRANSLATION"}, value = {
    @IntDef(prefix = {"STATE__TRANSLATION"}, value = {
            STATE_UI_TRANSLATION_STARTED,
            STATE_UI_TRANSLATION_STARTED,
            STATE_UI_TRANSLATION_PAUSED,
            STATE_UI_TRANSLATION_PAUSED,
@@ -145,6 +144,8 @@ public final class UiTranslationManager {
    public static final String EXTRA_SOURCE_LOCALE = "source_locale";
    public static final String EXTRA_SOURCE_LOCALE = "source_locale";
    /** @hide */
    /** @hide */
    public static final String EXTRA_TARGET_LOCALE = "target_locale";
    public static final String EXTRA_TARGET_LOCALE = "target_locale";
    /** @hide */
    public static final String EXTRA_PACKAGE_NAME = "package_name";


    @NonNull
    @NonNull
    private final Context mContext;
    private final Context mContext;
@@ -215,7 +216,7 @@ public final class UiTranslationManager {


    /**
    /**
     * Request to disable the ui translation. It will destroy all the {@link Translator}s and no
     * Request to disable the ui translation. It will destroy all the {@link Translator}s and no
     * longer to show to show the translated text.
     * longer to show the translated text.
     *
     *
     * @param activityId the identifier for the Activity which needs ui translation
     * @param activityId the identifier for the Activity which needs ui translation
     * @throws NullPointerException the activityId or
     * @throws NullPointerException the activityId or
@@ -362,8 +363,8 @@ public final class UiTranslationManager {
    public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId,
    public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId,
            ComponentName componentName) {
            ComponentName componentName) {
        try {
        try {
            mService.onTranslationFinished(activityDestroyed,
            mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName,
                    activityId.getToken(), componentName, mContext.getUserId());
                    mContext.getUserId());
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
@@ -392,20 +393,21 @@ public final class UiTranslationManager {


        private void onStateChange(Bundle bundle) {
        private void onStateChange(Bundle bundle) {
            int state = bundle.getInt(EXTRA_STATE);
            int state = bundle.getInt(EXTRA_STATE);
            String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
            switch (state) {
            switch (state) {
                case STATE_UI_TRANSLATION_STARTED:
                case STATE_UI_TRANSLATION_STARTED:
                    mSourceLocale = (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE);
                    mSourceLocale = bundle.getSerializable(EXTRA_SOURCE_LOCALE, ULocale.class);
                    mTargetLocale = (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE);
                    mTargetLocale = bundle.getSerializable(EXTRA_TARGET_LOCALE, ULocale.class);
                    mCallback.onStarted(mSourceLocale, mTargetLocale);
                    mCallback.onStarted(mSourceLocale, mTargetLocale, packageName);
                    break;
                    break;
                case STATE_UI_TRANSLATION_RESUMED:
                case STATE_UI_TRANSLATION_RESUMED:
                    mCallback.onResumed(mSourceLocale, mTargetLocale);
                    mCallback.onResumed(mSourceLocale, mTargetLocale, packageName);
                    break;
                    break;
                case STATE_UI_TRANSLATION_PAUSED:
                case STATE_UI_TRANSLATION_PAUSED:
                    mCallback.onPaused();
                    mCallback.onPaused(packageName);
                    break;
                    break;
                case STATE_UI_TRANSLATION_FINISHED:
                case STATE_UI_TRANSLATION_FINISHED:
                    mCallback.onFinished();
                    mCallback.onFinished(packageName);
                    break;
                    break;
                default:
                default:
                    Log.wtf(TAG, "Unexpected translation state:" + state);
                    Log.wtf(TAG, "Unexpected translation state:" + state);
+108 −3
Original line number Original line Diff line number Diff line
@@ -24,11 +24,21 @@ import java.util.concurrent.Executor;
/**
/**
 * Callback for listening to UI Translation state changes. See {@link
 * Callback for listening to UI Translation state changes. See {@link
 * UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}.
 * UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}.
 * <p>
 * Prior to Android version {@link android.os.Build.VERSION_CODES#TIRAMISU}, callback methods
 * <em>without</em> {@code packageName} are invoked. Apps with minSdkVersion lower than {@link
 * android.os.Build.VERSION_CODES#TIRAMISU} <em>must</em> implement those methods if they want to
 * handle the events.
 * <p>
 * In Android version {@link android.os.Build.VERSION_CODES#TIRAMISU} and later, if both methods
 * with and without {@code packageName} are implemented (e.g., {@link #onFinished()} and {@link
 * #onFinished(String)}, only the one <em>with</em> {@code packageName} will be called.
 */
 */
public interface UiTranslationStateCallback {
public interface UiTranslationStateCallback {


    /**
    /**
     * @removed use {@link #onStarted(ULocale, ULocale)} instead.
     * @removed use {@link #onStarted(ULocale, ULocale)} or {@link #onStarted(ULocale, ULocale,
     * String)} instead.
     */
     */
    @Deprecated
    @Deprecated
    default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) {
    default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) {
@@ -41,27 +51,122 @@ public interface UiTranslationStateCallback {
     * <p>
     * <p>
     * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has
     * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has
     * changed.
     * changed.
     * <p>
     * Apps should implement {@link #onStarted(ULocale, ULocale, String)} instead if they need the
     * name of the package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement this method if they want to handle the "started" event.
     *
     * @param sourceLocale {@link ULocale} the UI is being translated from.
     * @param targetLocale {@link ULocale} the UI is being translated to.
     */
     */
    default void onStarted(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) {
    default void onStarted(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) {
        onStarted(sourceLocale.getLanguage(), targetLocale.getLanguage());
        onStarted(sourceLocale.getLanguage(), targetLocale.getLanguage());
    }
    }


    /**
     * The system is requesting translation of the UI from {@code sourceLocale} to {@code
     * targetLocale}.
     * <p>
     * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has
     * changed.
     * <p>
     * Apps <em>may</em> implement {@link #onStarted(ULocale, ULocale)} instead if they don't need
     * the name of the package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement {@link #onStarted(ULocale, ULocale)} if they want to handle the
     * "started" event.
     *
     * @param sourceLocale {@link ULocale} the UI is being translated from.
     * @param targetLocale {@link ULocale} the UI is being translated to.
     * @param packageName  The name of the package that owns the activity being translated.
     */
    default void onStarted(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale,
            @NonNull String packageName) {
        onStarted(sourceLocale, targetLocale);
    }

    /**
    /**
     * The system is requesting that the application temporarily show the UI contents in their
     * The system is requesting that the application temporarily show the UI contents in their
     * original language.
     * original language.
     * <p>
     * Apps should implement {@link #onPaused(String)} as well if they need the name of the
     * package that owns the activity being translated.
     */
     */
    void onPaused();
    void onPaused();


    /**
     * The system is requesting that the application temporarily show the UI contents in their
     * original language.
     * <p>
     * Apps <em>may</em> implement {@link #onPaused()} instead if they don't need the name of the
     * package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement {@link #onPaused()} if they want to handle the "paused" event.
     */
    default void onPaused(@NonNull String packageName) {
        onPaused();
    }

    /**
    /**
     * The system is requesting that the application restore from the temporarily paused state and
     * The system is requesting that the application restore from the temporarily paused state and
     * show the content in translated language.
     * show the content in the translated language.
     * <p>
     * Apps should implement {@link #onResumed(ULocale, ULocale, String)} instead if they need the
     * name of the package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement this method if they want to handle the "resumed" event.
     *
     * @param sourceLocale {@link ULocale} the UI is being translated from.
     * @param targetLocale {@link ULocale} the UI is being translated to.
     */
     */
    // TODO: Remove the default implementation when clients have implemented this.
    default void onResumed(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) {
    default void onResumed(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale) {
    }
    }


    /**
     * The system is requesting that the application restore from the temporarily paused state and
     * show the content in the translated language.
     * <p>
     * Apps <em>may</em> implement {@link #onResumed(ULocale, ULocale)} instead if they don't need
     * the name of the package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement {@link #onResumed(ULocale, ULocale)} if they want to handle the
     * "resumed" event.
     *
     * @param sourceLocale {@link ULocale} the UI is being translated from.
     * @param targetLocale {@link ULocale} the UI is being translated to.
     * @param packageName  The name of the package that owns the activity being translated.
     */
    default void onResumed(@NonNull ULocale sourceLocale, @NonNull ULocale targetLocale,
            @NonNull String packageName) {
        onResumed(sourceLocale, targetLocale);
    }

    /**
    /**
     * The UI Translation session has ended.
     * The UI Translation session has ended.
     * <p>
     * Apps should implement {@link #onFinished(String)} as well if they need the name of the
     * package that owns the activity being translated.
     */
     */
    void onFinished();
    void onFinished();

    /**
     * The UI Translation session has ended.
     * <p>
     * Apps <em>may</em> implement {@link #onFinished()} instead if they don't need the name of the
     * package that owns the activity being translated.
     * <p>
     * Apps with minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * <em>must</em> implement {@link #onFinished()} if they want to handle the "finished" event.
     *
     * @param packageName The name of the package that owns the activity being translated.
     */
    default void onFinished(@NonNull String packageName) {
        onFinished();
    }
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ public interface ViewTranslationCallback {
    /**
    /**
     * Called when user wants to view the original content instead of the translated content. This
     * Called when user wants to view the original content instead of the translated content. This
     * method will not be called before {@link View#onViewTranslationResponse} or
     * method will not be called before {@link View#onViewTranslationResponse} or
     * {@link View#onViewTranslationResponse}.
     * {@link View#onVirtualViewTranslationResponses}.
     *
     *
     * @return {@code true} if the View handles hiding the translation.
     * @return {@code true} if the View handles hiding the translation.
     */
     */
+29 −19
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.translation;
package com.android.server.translation;


import static android.view.translation.TranslationManager.EXTRA_CAPABILITIES;
import static android.view.translation.TranslationManager.EXTRA_CAPABILITIES;
import static android.view.translation.UiTranslationManager.EXTRA_PACKAGE_NAME;
import static android.view.translation.UiTranslationManager.EXTRA_SOURCE_LOCALE;
import static android.view.translation.UiTranslationManager.EXTRA_SOURCE_LOCALE;
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE;
import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE;
@@ -192,19 +193,22 @@ final class TranslationManagerServiceImpl extends
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token,
    public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token,
            ComponentName componentName) {
            ComponentName componentName) {
        int translationActivityUid =
        final int translationActivityUid =
                getActivityUidByComponentName(getContext(), componentName, getUserId());
                getActivityUidByComponentName(getContext(), componentName, getUserId());
        final String packageName = componentName.getPackageName();
        if (activityDestroyed) {
        if (activityDestroyed) {
            // In the Activity destroy case, we only calls onTranslationFinished() in
            // In the Activity destroy case, we only calls onTranslationFinished() in
            // non-finisTranslation() state. If there is a finisTranslation() calls by apps, we
            // non-finisTranslation() state. If there is a finisTranslation() calls by apps, we
            // should remove the waiting callback to avoid callback twice.
            // should remove the waiting callback to avoid callback twice.
            invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */
            invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
                    null, /* targetSpec= */null, translationActivityUid);
                    /* sourceSpec= */ null, /* targetSpec= */ null,
                    packageName, translationActivityUid);
            mWaitingFinishedCallbackActivities.remove(token);
            mWaitingFinishedCallbackActivities.remove(token);
        } else {
        } else {
            if (mWaitingFinishedCallbackActivities.contains(token)) {
            if (mWaitingFinishedCallbackActivities.contains(token)) {
                invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */
                invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
                        null, /* targetSpec= */null, translationActivityUid);
                        /* sourceSpec= */ null, /* targetSpec= */ null,
                        packageName, translationActivityUid);
                mWaitingFinishedCallbackActivities.remove(token);
                mWaitingFinishedCallbackActivities.remove(token);
            }
            }
        }
        }
@@ -223,25 +227,25 @@ final class TranslationManagerServiceImpl extends
                    + "state for token=" + token + " taskId=" + taskId + " for state= " + state);
                    + "state for token=" + token + " taskId=" + taskId + " for state= " + state);
            return;
            return;
        }
        }
        mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
        if (state == STATE_UI_TRANSLATION_FINISHED) {
        if (state == STATE_UI_TRANSLATION_FINISHED) {
            mWaitingFinishedCallbackActivities.add(token);
            mWaitingFinishedCallbackActivities.add(token);
        }
        }
        int translationActivityUid = -1;
        try {
        IBinder activityToken = taskTopActivityTokens.getActivityToken();
        IBinder activityToken = taskTopActivityTokens.getActivityToken();
        try {
            taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
            taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
                    activityToken, state, sourceSpec, targetSpec,
                    activityToken, state, sourceSpec, targetSpec,
                    viewIds, uiTranslationSpec);
                    viewIds, uiTranslationSpec);
            mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
            ComponentName componentName =
                    mActivityTaskManagerInternal.getActivityName(activityToken);
            translationActivityUid =
                    getActivityUidByComponentName(getContext(), componentName, getUserId());
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Slog.w(TAG, "Update UiTranslationState fail: " + e);
            Slog.w(TAG, "Update UiTranslationState fail: " + e);
        }
        }

        ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken);
        int translationActivityUid =
                getActivityUidByComponentName(getContext(), componentName, getUserId());
        if (state != STATE_UI_TRANSLATION_FINISHED) {
        if (state != STATE_UI_TRANSLATION_FINISHED) {
            invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid);
            invokeCallbacks(state, sourceSpec, targetSpec, componentName.getPackageName(),
                    translationActivityUid);
        }
        }
    }
    }


@@ -266,20 +270,24 @@ final class TranslationManagerServiceImpl extends
                pw.println(prefix + "Got a RemoteException while dumping the activity");
                pw.println(prefix + "Got a RemoteException while dumping the activity");
            }
            }
        } else {
        } else {
            pw.print(prefix); pw.println("No requested UiTranslation Activity.");
            pw.print(prefix);
            pw.println("No requested UiTranslation Activity.");
        }
        }
        final int waitingFinishCallbackSize = mWaitingFinishedCallbackActivities.size();
        final int waitingFinishCallbackSize = mWaitingFinishedCallbackActivities.size();
        if (waitingFinishCallbackSize > 0) {
        if (waitingFinishCallbackSize > 0) {
            pw.print(prefix); pw.print("number waiting finish callback activities: ");
            pw.print(prefix);
            pw.print("number waiting finish callback activities: ");
            pw.println(waitingFinishCallbackSize);
            pw.println(waitingFinishCallbackSize);
            for (IBinder activityToken : mWaitingFinishedCallbackActivities) {
            for (IBinder activityToken : mWaitingFinishedCallbackActivities) {
                pw.print(prefix); pw.print("activityToken: "); pw.println(activityToken);
                pw.print(prefix);
                pw.print("activityToken: ");
                pw.println(activityToken);
            }
            }
        }
        }
    }
    }


    private void invokeCallbacks(
    private void invokeCallbacks(
            int state, TranslationSpec sourceSpec, TranslationSpec targetSpec,
            int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName,
            int translationActivityUid) {
            int translationActivityUid) {
        Bundle res = new Bundle();
        Bundle res = new Bundle();
        res.putInt(EXTRA_STATE, state);
        res.putInt(EXTRA_STATE, state);
@@ -288,6 +296,7 @@ final class TranslationManagerServiceImpl extends
            res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale());
            res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale());
            res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale());
            res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale());
        }
        }
        res.putString(EXTRA_PACKAGE_NAME, packageName);
        // TODO(177500482): Only support the *current* Input Method.
        // TODO(177500482): Only support the *current* Input Method.
        List<InputMethodInfo> enabledInputMethods =
        List<InputMethodInfo> enabledInputMethods =
                LocalServices.getService(InputMethodManagerInternal.class)
                LocalServices.getService(InputMethodManagerInternal.class)
@@ -299,6 +308,7 @@ final class TranslationManagerServiceImpl extends
                } catch (RemoteException e) {
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
                    Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
                }
                }
                return;
            }
            }
            // Code here is non-optimal since it's temporary..
            // Code here is non-optimal since it's temporary..
            boolean isIme = false;
            boolean isIme = false;