Loading core/api/current.txt +11 −0 Original line number Diff line number Diff line Loading @@ -52411,6 +52411,17 @@ package android.view.translation { method @Nullable @WorkerThread public android.view.translation.TranslationResponse translate(@NonNull android.view.translation.TranslationRequest); } public final class UiTranslationManager { method public void registerUiTranslationStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.translation.UiTranslationStateCallback); method public void unregisterUiTranslationStateCallback(@NonNull android.view.translation.UiTranslationStateCallback); } public interface UiTranslationStateCallback { method public void onFinished(); method public void onPaused(); method public void onStarted(@NonNull String, @NonNull String); } public final class ViewTranslationRequest implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.view.autofill.AutofillId getAutofillId(); core/java/android/os/RemoteCallbackList.java +18 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.util.ArrayMap; import android.util.Slog; import java.io.PrintWriter; import java.util.function.BiConsumer; import java.util.function.Consumer; /** Loading Loading @@ -353,6 +354,23 @@ public class RemoteCallbackList<E extends IInterface> { } } /** * Performs {@code action} on each callback and associated cookie, calling {@link * #beginBroadcast()}/{@link #finishBroadcast()} before/after looping. * * @hide */ public <C> void broadcast(BiConsumer<E, C> action) { int itemCount = beginBroadcast(); try { for (int i = 0; i < itemCount; i++) { action.accept(getBroadcastItem(i), (C) getBroadcastCookie(i)); } } finally { finishBroadcast(); } } /** * Returns the number of registered callbacks. Note that the number of registered * callbacks may differ from the value returned by {@link #beginBroadcast()} since Loading core/java/android/view/translation/ITranslationManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view.translation; import android.os.IBinder; import android.os.IRemoteCallback; import android.view.autofill.AutofillId; import android.view.translation.TranslationSpec; import com.android.internal.os.IResultReceiver; Loading @@ -40,4 +41,7 @@ oneway interface ITranslationManager { void updateUiTranslationStateByTaskId(int state, in TranslationSpec sourceSpec, in TranslationSpec destSpec, in List<AutofillId> viewIds, int taskId, int userId); void registerUiTranslationStateCallback(in IRemoteCallback callback, int userId); void unregisterUiTranslationStateCallback(in IRemoteCallback callback, int userId); } core/java/android/view/translation/UiTranslationManager.java +144 −3 Original line number Diff line number Diff line Loading @@ -16,28 +16,36 @@ package android.view.translation; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.assist.ActivityId; import android.content.Context; import android.os.Binder; import android.os.Bundle; import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; import android.view.View; import android.view.autofill.AutofillId; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; // TODO(b/178044703): Describe what UI Translation is. /** * The {@link UiTranslationManager} class provides ways for apps to use the ui translation * function in framework. * * @hide */ @SystemApi public final class UiTranslationManager { private static final String TAG = "UiTranslationManager"; Loading Loading @@ -88,6 +96,14 @@ public final class UiTranslationManager { public @interface UiTranslationState { } // Keys for the data transmitted in the internal UI Translation state callback. /** @hide */ public static final String EXTRA_STATE = "state"; /** @hide */ public static final String EXTRA_SOURCE_LOCALE = "source_locale"; /** @hide */ public static final String EXTRA_TARGET_LOCALE = "target_locale"; @NonNull private final Context mContext; Loading @@ -111,9 +127,12 @@ public final class UiTranslationManager { * @param destSpec {@link TranslationSpec} for the translated data. * @param viewIds A list of the {@link View}'s {@link AutofillId} which needs to be translated * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void startTranslation(@NonNull TranslationSpec sourceSpec, @NonNull TranslationSpec destSpec, @NonNull List<AutofillId> viewIds, int taskId) { Loading Loading @@ -141,8 +160,11 @@ public final class UiTranslationManager { * @throws IllegalArgumentException if the no {@link View}'s {@link AutofillId} in the list * @throws NullPointerException the sourceSpec, destSpec, viewIds, activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void startTranslation(@NonNull TranslationSpec sourceSpec, @NonNull TranslationSpec destSpec, @NonNull List<AutofillId> viewIds, @NonNull ActivityId activityId) { Loading Loading @@ -171,9 +193,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code finishTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void finishTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_FINISHED, Loading @@ -191,8 +216,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void finishTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -212,9 +240,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code pauseTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void pauseTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_PAUSED, Loading @@ -232,8 +263,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void pauseTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -253,9 +287,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code resumeTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void resumeTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_RESUMED, Loading @@ -273,8 +310,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void resumeTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -286,4 +326,105 @@ public final class UiTranslationManager { throw e.rethrowFromSystemServer(); } } // TODO(b/178044703): Fix the View API link when it becomes public. /** * Register for notifications of UI Translation state changes on the foreground activity. This * is available to the owning application itself and also the current input method. * <p> * The application whose UI is being translated can use this to customize the UI Translation * behavior in ways that aren't made easy by methods like * View#onCreateTranslationRequest(). * <p> * Input methods can use this to offer complementary features to UI Translation; for example, * enabling outgoing message translation when the system is translating incoming messages in a * communication app. * * @param callback the callback to register for receiving the state change * notifications */ public void registerUiTranslationStateCallback( @NonNull @CallbackExecutor Executor executor, @NonNull UiTranslationStateCallback callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); synchronized (mCallbacks) { if (mCallbacks.containsKey(callback)) { Log.w(TAG, "registerUiTranslationStateCallback: callback already registered;" + " ignoring."); return; } final IRemoteCallback remoteCallback = new UiTranslationStateRemoteCallback(executor, callback); try { mService.registerUiTranslationStateCallback(remoteCallback, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCallbacks.put(callback, remoteCallback); } } /** * Unregister {@code callback}. * * @see #registerUiTranslationStateCallback(Executor, UiTranslationStateCallback) */ public void unregisterUiTranslationStateCallback(@NonNull UiTranslationStateCallback callback) { Objects.requireNonNull(callback); synchronized (mCallbacks) { final IRemoteCallback remoteCallback = mCallbacks.get(callback); if (remoteCallback == null) { Log.w(TAG, "unregisterUiTranslationStateCallback: callback not found; ignoring."); return; } try { mService.unregisterUiTranslationStateCallback(remoteCallback, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCallbacks.remove(callback); } } @NonNull @GuardedBy("mCallbacks") private final Map<UiTranslationStateCallback, IRemoteCallback> mCallbacks = new ArrayMap<>(); private static class UiTranslationStateRemoteCallback extends IRemoteCallback.Stub { private final Executor mExecutor; private final UiTranslationStateCallback mCallback; UiTranslationStateRemoteCallback(Executor executor, UiTranslationStateCallback callback) { mExecutor = executor; mCallback = callback; } @Override public void sendResult(Bundle bundle) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> onStateChange(bundle))); } private void onStateChange(Bundle bundle) { int state = bundle.getInt(EXTRA_STATE); switch (state) { case STATE_UI_TRANSLATION_STARTED: case STATE_UI_TRANSLATION_RESUMED: mCallback.onStarted( bundle.getString(EXTRA_SOURCE_LOCALE), bundle.getString(EXTRA_TARGET_LOCALE)); break; case STATE_UI_TRANSLATION_PAUSED: mCallback.onPaused(); break; case STATE_UI_TRANSLATION_FINISHED: mCallback.onFinished(); break; default: Log.wtf(TAG, "Unexpected translation state:" + state); } } } } core/java/android/view/translation/UiTranslationStateCallback.java 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.translation; import android.annotation.NonNull; import java.util.concurrent.Executor; /** * Callback for listening to UI Translation state changes. See {@link * UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}. */ public interface UiTranslationStateCallback { /** * 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; or called again after {@link #onPaused()}. */ void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale); /** * The system is requesting that the application temporarily show the UI contents in their * original language. */ void onPaused(); /** * The UI Translation session has ended. */ void onFinished(); } Loading
core/api/current.txt +11 −0 Original line number Diff line number Diff line Loading @@ -52411,6 +52411,17 @@ package android.view.translation { method @Nullable @WorkerThread public android.view.translation.TranslationResponse translate(@NonNull android.view.translation.TranslationRequest); } public final class UiTranslationManager { method public void registerUiTranslationStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.translation.UiTranslationStateCallback); method public void unregisterUiTranslationStateCallback(@NonNull android.view.translation.UiTranslationStateCallback); } public interface UiTranslationStateCallback { method public void onFinished(); method public void onPaused(); method public void onStarted(@NonNull String, @NonNull String); } public final class ViewTranslationRequest implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.view.autofill.AutofillId getAutofillId();
core/java/android/os/RemoteCallbackList.java +18 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.util.ArrayMap; import android.util.Slog; import java.io.PrintWriter; import java.util.function.BiConsumer; import java.util.function.Consumer; /** Loading Loading @@ -353,6 +354,23 @@ public class RemoteCallbackList<E extends IInterface> { } } /** * Performs {@code action} on each callback and associated cookie, calling {@link * #beginBroadcast()}/{@link #finishBroadcast()} before/after looping. * * @hide */ public <C> void broadcast(BiConsumer<E, C> action) { int itemCount = beginBroadcast(); try { for (int i = 0; i < itemCount; i++) { action.accept(getBroadcastItem(i), (C) getBroadcastCookie(i)); } } finally { finishBroadcast(); } } /** * Returns the number of registered callbacks. Note that the number of registered * callbacks may differ from the value returned by {@link #beginBroadcast()} since Loading
core/java/android/view/translation/ITranslationManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view.translation; import android.os.IBinder; import android.os.IRemoteCallback; import android.view.autofill.AutofillId; import android.view.translation.TranslationSpec; import com.android.internal.os.IResultReceiver; Loading @@ -40,4 +41,7 @@ oneway interface ITranslationManager { void updateUiTranslationStateByTaskId(int state, in TranslationSpec sourceSpec, in TranslationSpec destSpec, in List<AutofillId> viewIds, int taskId, int userId); void registerUiTranslationStateCallback(in IRemoteCallback callback, int userId); void unregisterUiTranslationStateCallback(in IRemoteCallback callback, int userId); }
core/java/android/view/translation/UiTranslationManager.java +144 −3 Original line number Diff line number Diff line Loading @@ -16,28 +16,36 @@ package android.view.translation; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.assist.ActivityId; import android.content.Context; import android.os.Binder; import android.os.Bundle; import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; import android.view.View; import android.view.autofill.AutofillId; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; // TODO(b/178044703): Describe what UI Translation is. /** * The {@link UiTranslationManager} class provides ways for apps to use the ui translation * function in framework. * * @hide */ @SystemApi public final class UiTranslationManager { private static final String TAG = "UiTranslationManager"; Loading Loading @@ -88,6 +96,14 @@ public final class UiTranslationManager { public @interface UiTranslationState { } // Keys for the data transmitted in the internal UI Translation state callback. /** @hide */ public static final String EXTRA_STATE = "state"; /** @hide */ public static final String EXTRA_SOURCE_LOCALE = "source_locale"; /** @hide */ public static final String EXTRA_TARGET_LOCALE = "target_locale"; @NonNull private final Context mContext; Loading @@ -111,9 +127,12 @@ public final class UiTranslationManager { * @param destSpec {@link TranslationSpec} for the translated data. * @param viewIds A list of the {@link View}'s {@link AutofillId} which needs to be translated * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void startTranslation(@NonNull TranslationSpec sourceSpec, @NonNull TranslationSpec destSpec, @NonNull List<AutofillId> viewIds, int taskId) { Loading Loading @@ -141,8 +160,11 @@ public final class UiTranslationManager { * @throws IllegalArgumentException if the no {@link View}'s {@link AutofillId} in the list * @throws NullPointerException the sourceSpec, destSpec, viewIds, activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void startTranslation(@NonNull TranslationSpec sourceSpec, @NonNull TranslationSpec destSpec, @NonNull List<AutofillId> viewIds, @NonNull ActivityId activityId) { Loading Loading @@ -171,9 +193,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code finishTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void finishTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_FINISHED, Loading @@ -191,8 +216,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void finishTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -212,9 +240,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code pauseTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void pauseTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_PAUSED, Loading @@ -232,8 +263,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void pauseTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -253,9 +287,12 @@ public final class UiTranslationManager { * NOTE: Please use {@code resumeTranslation(ActivityId)} instead. * * @param taskId the Activity Task id which needs ui translation * * @hide */ // TODO, hide the APIs @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void resumeTranslation(int taskId) { try { mService.updateUiTranslationStateByTaskId(STATE_UI_TRANSLATION_RESUMED, Loading @@ -273,8 +310,11 @@ public final class UiTranslationManager { * @param activityId the identifier for the Activity which needs ui translation * @throws NullPointerException the activityId or * {@link android.app.assist.ActivityId#getToken()} is {@code null} * * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) @SystemApi public void resumeTranslation(@NonNull ActivityId activityId) { try { Objects.requireNonNull(activityId); Loading @@ -286,4 +326,105 @@ public final class UiTranslationManager { throw e.rethrowFromSystemServer(); } } // TODO(b/178044703): Fix the View API link when it becomes public. /** * Register for notifications of UI Translation state changes on the foreground activity. This * is available to the owning application itself and also the current input method. * <p> * The application whose UI is being translated can use this to customize the UI Translation * behavior in ways that aren't made easy by methods like * View#onCreateTranslationRequest(). * <p> * Input methods can use this to offer complementary features to UI Translation; for example, * enabling outgoing message translation when the system is translating incoming messages in a * communication app. * * @param callback the callback to register for receiving the state change * notifications */ public void registerUiTranslationStateCallback( @NonNull @CallbackExecutor Executor executor, @NonNull UiTranslationStateCallback callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); synchronized (mCallbacks) { if (mCallbacks.containsKey(callback)) { Log.w(TAG, "registerUiTranslationStateCallback: callback already registered;" + " ignoring."); return; } final IRemoteCallback remoteCallback = new UiTranslationStateRemoteCallback(executor, callback); try { mService.registerUiTranslationStateCallback(remoteCallback, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCallbacks.put(callback, remoteCallback); } } /** * Unregister {@code callback}. * * @see #registerUiTranslationStateCallback(Executor, UiTranslationStateCallback) */ public void unregisterUiTranslationStateCallback(@NonNull UiTranslationStateCallback callback) { Objects.requireNonNull(callback); synchronized (mCallbacks) { final IRemoteCallback remoteCallback = mCallbacks.get(callback); if (remoteCallback == null) { Log.w(TAG, "unregisterUiTranslationStateCallback: callback not found; ignoring."); return; } try { mService.unregisterUiTranslationStateCallback(remoteCallback, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCallbacks.remove(callback); } } @NonNull @GuardedBy("mCallbacks") private final Map<UiTranslationStateCallback, IRemoteCallback> mCallbacks = new ArrayMap<>(); private static class UiTranslationStateRemoteCallback extends IRemoteCallback.Stub { private final Executor mExecutor; private final UiTranslationStateCallback mCallback; UiTranslationStateRemoteCallback(Executor executor, UiTranslationStateCallback callback) { mExecutor = executor; mCallback = callback; } @Override public void sendResult(Bundle bundle) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> onStateChange(bundle))); } private void onStateChange(Bundle bundle) { int state = bundle.getInt(EXTRA_STATE); switch (state) { case STATE_UI_TRANSLATION_STARTED: case STATE_UI_TRANSLATION_RESUMED: mCallback.onStarted( bundle.getString(EXTRA_SOURCE_LOCALE), bundle.getString(EXTRA_TARGET_LOCALE)); break; case STATE_UI_TRANSLATION_PAUSED: mCallback.onPaused(); break; case STATE_UI_TRANSLATION_FINISHED: mCallback.onFinished(); break; default: Log.wtf(TAG, "Unexpected translation state:" + state); } } } }
core/java/android/view/translation/UiTranslationStateCallback.java 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.translation; import android.annotation.NonNull; import java.util.concurrent.Executor; /** * Callback for listening to UI Translation state changes. See {@link * UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}. */ public interface UiTranslationStateCallback { /** * 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; or called again after {@link #onPaused()}. */ void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale); /** * The system is requesting that the application temporarily show the UI contents in their * original language. */ void onPaused(); /** * The UI Translation session has ended. */ void onFinished(); }