Loading core/api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -54124,9 +54124,13 @@ package android.view.translation { public interface UiTranslationStateCallback { method public void onFinished(); method public default void onFinished(@NonNull String); 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, @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, @NonNull String); } @UiThread public interface ViewTranslationCallback { core/java/android/view/translation/UiTranslationManager.java +18 −16 Original line number Diff line number Diff line Loading @@ -101,33 +101,32 @@ public final class UiTranslationManager { 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 */ 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 */ 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. * * @hide */ 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 */ public static final int STATE_UI_TRANSLATION_FINISHED = 3; /** * @hide */ /** @hide */ @IntDef(prefix = {"STATE__TRANSLATION"}, value = { STATE_UI_TRANSLATION_STARTED, STATE_UI_TRANSLATION_PAUSED, Loading @@ -145,6 +144,8 @@ public final class UiTranslationManager { public static final String EXTRA_SOURCE_LOCALE = "source_locale"; /** @hide */ public static final String EXTRA_TARGET_LOCALE = "target_locale"; /** @hide */ public static final String EXTRA_PACKAGE_NAME = "package_name"; @NonNull private final Context mContext; Loading Loading @@ -215,7 +216,7 @@ public final class UiTranslationManager { /** * 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 * @throws NullPointerException the activityId or Loading Loading @@ -362,8 +363,8 @@ public final class UiTranslationManager { public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId, ComponentName componentName) { try { mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName, mContext.getUserId()); mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -392,20 +393,21 @@ public final class UiTranslationManager { private void onStateChange(Bundle bundle) { int state = bundle.getInt(EXTRA_STATE); String packageName = bundle.getString(EXTRA_PACKAGE_NAME); switch (state) { case STATE_UI_TRANSLATION_STARTED: mSourceLocale = (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE); mTargetLocale = (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE); mCallback.onStarted(mSourceLocale, mTargetLocale); mSourceLocale = bundle.getSerializable(EXTRA_SOURCE_LOCALE, ULocale.class); mTargetLocale = bundle.getSerializable(EXTRA_TARGET_LOCALE, ULocale.class); mCallback.onStarted(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_RESUMED: mCallback.onResumed(mSourceLocale, mTargetLocale); mCallback.onResumed(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_PAUSED: mCallback.onPaused(); mCallback.onPaused(packageName); break; case STATE_UI_TRANSLATION_FINISHED: mCallback.onFinished(); mCallback.onFinished(packageName); break; default: Log.wtf(TAG, "Unexpected translation state:" + state); Loading core/java/android/view/translation/UiTranslationStateCallback.java +108 −3 Original line number Diff line number Diff line Loading @@ -24,11 +24,21 @@ import java.util.concurrent.Executor; /** * Callback for listening to UI Translation state changes. See {@link * 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 { /** * @removed use {@link #onStarted(ULocale, ULocale)} instead. * @removed use {@link #onStarted(ULocale, ULocale)} or {@link #onStarted(ULocale, ULocale, * String)} instead. */ @Deprecated default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) { Loading @@ -41,27 +51,122 @@ public interface UiTranslationStateCallback { * <p> * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has * 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) { 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 * 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(); /** * 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 * 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) { } /** * 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. * <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(); /** * 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(); } } core/java/android/view/translation/ViewTranslationCallback.java +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ public interface ViewTranslationCallback { /** * 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 * {@link View#onViewTranslationResponse}. * {@link View#onVirtualViewTranslationResponses}. * * @return {@code true} if the View handles hiding the translation. */ Loading services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java +29 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.translation; 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_STATE; import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE; Loading Loading @@ -192,19 +193,22 @@ final class TranslationManagerServiceImpl extends @GuardedBy("mLock") public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token, ComponentName componentName) { int translationActivityUid = final int translationActivityUid = getActivityUidByComponentName(getContext(), componentName, getUserId()); final String packageName = componentName.getPackageName(); if (activityDestroyed) { // In the Activity destroy case, we only calls onTranslationFinished() in // non-finisTranslation() state. If there is a finisTranslation() calls by apps, we // should remove the waiting callback to avoid callback twice. invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */null, translationActivityUid); invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */ null, packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } else { if (mWaitingFinishedCallbackActivities.contains(token)) { invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */null, translationActivityUid); invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */ null, packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } } Loading @@ -223,25 +227,25 @@ final class TranslationManagerServiceImpl extends + "state for token=" + token + " taskId=" + taskId + " for state= " + state); return; } mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); if (state == STATE_UI_TRANSLATION_FINISHED) { mWaitingFinishedCallbackActivities.add(token); } int translationActivityUid = -1; try { IBinder activityToken = taskTopActivityTokens.getActivityToken(); try { taskTopActivityTokens.getApplicationThread().updateUiTranslationState( activityToken, state, sourceSpec, targetSpec, viewIds, uiTranslationSpec); mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken); translationActivityUid = getActivityUidByComponentName(getContext(), componentName, getUserId()); } catch (RemoteException 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) { invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid); invokeCallbacks(state, sourceSpec, targetSpec, componentName.getPackageName(), translationActivityUid); } } Loading @@ -266,20 +270,24 @@ final class TranslationManagerServiceImpl extends pw.println(prefix + "Got a RemoteException while dumping the activity"); } } else { pw.print(prefix); pw.println("No requested UiTranslation Activity."); pw.print(prefix); pw.println("No requested UiTranslation Activity."); } final int waitingFinishCallbackSize = mWaitingFinishedCallbackActivities.size(); 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); 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( int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName, int translationActivityUid) { Bundle res = new Bundle(); res.putInt(EXTRA_STATE, state); Loading @@ -288,6 +296,7 @@ final class TranslationManagerServiceImpl extends res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale()); res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale()); } res.putString(EXTRA_PACKAGE_NAME, packageName); // TODO(177500482): Only support the *current* Input Method. List<InputMethodInfo> enabledInputMethods = LocalServices.getService(InputMethodManagerInternal.class) Loading @@ -299,6 +308,7 @@ final class TranslationManagerServiceImpl extends } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e); } return; } // Code here is non-optimal since it's temporary.. boolean isIme = false; Loading Loading
core/api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -54124,9 +54124,13 @@ package android.view.translation { public interface UiTranslationStateCallback { method public void onFinished(); method public default void onFinished(@NonNull String); 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, @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, @NonNull String); } @UiThread public interface ViewTranslationCallback {
core/java/android/view/translation/UiTranslationManager.java +18 −16 Original line number Diff line number Diff line Loading @@ -101,33 +101,32 @@ public final class UiTranslationManager { 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 */ 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 */ 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. * * @hide */ 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 */ public static final int STATE_UI_TRANSLATION_FINISHED = 3; /** * @hide */ /** @hide */ @IntDef(prefix = {"STATE__TRANSLATION"}, value = { STATE_UI_TRANSLATION_STARTED, STATE_UI_TRANSLATION_PAUSED, Loading @@ -145,6 +144,8 @@ public final class UiTranslationManager { public static final String EXTRA_SOURCE_LOCALE = "source_locale"; /** @hide */ public static final String EXTRA_TARGET_LOCALE = "target_locale"; /** @hide */ public static final String EXTRA_PACKAGE_NAME = "package_name"; @NonNull private final Context mContext; Loading Loading @@ -215,7 +216,7 @@ public final class UiTranslationManager { /** * 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 * @throws NullPointerException the activityId or Loading Loading @@ -362,8 +363,8 @@ public final class UiTranslationManager { public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId, ComponentName componentName) { try { mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName, mContext.getUserId()); mService.onTranslationFinished(activityDestroyed, activityId.getToken(), componentName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -392,20 +393,21 @@ public final class UiTranslationManager { private void onStateChange(Bundle bundle) { int state = bundle.getInt(EXTRA_STATE); String packageName = bundle.getString(EXTRA_PACKAGE_NAME); switch (state) { case STATE_UI_TRANSLATION_STARTED: mSourceLocale = (ULocale) bundle.getSerializable(EXTRA_SOURCE_LOCALE); mTargetLocale = (ULocale) bundle.getSerializable(EXTRA_TARGET_LOCALE); mCallback.onStarted(mSourceLocale, mTargetLocale); mSourceLocale = bundle.getSerializable(EXTRA_SOURCE_LOCALE, ULocale.class); mTargetLocale = bundle.getSerializable(EXTRA_TARGET_LOCALE, ULocale.class); mCallback.onStarted(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_RESUMED: mCallback.onResumed(mSourceLocale, mTargetLocale); mCallback.onResumed(mSourceLocale, mTargetLocale, packageName); break; case STATE_UI_TRANSLATION_PAUSED: mCallback.onPaused(); mCallback.onPaused(packageName); break; case STATE_UI_TRANSLATION_FINISHED: mCallback.onFinished(); mCallback.onFinished(packageName); break; default: Log.wtf(TAG, "Unexpected translation state:" + state); Loading
core/java/android/view/translation/UiTranslationStateCallback.java +108 −3 Original line number Diff line number Diff line Loading @@ -24,11 +24,21 @@ import java.util.concurrent.Executor; /** * Callback for listening to UI Translation state changes. See {@link * 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 { /** * @removed use {@link #onStarted(ULocale, ULocale)} instead. * @removed use {@link #onStarted(ULocale, ULocale)} or {@link #onStarted(ULocale, ULocale, * String)} instead. */ @Deprecated default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) { Loading @@ -41,27 +51,122 @@ public interface UiTranslationStateCallback { * <p> * This is also called if either the requested {@code sourceLocale} or {@code targetLocale} has * 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) { 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 * 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(); /** * 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 * 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) { } /** * 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. * <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(); /** * 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(); } }
core/java/android/view/translation/ViewTranslationCallback.java +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ public interface ViewTranslationCallback { /** * 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 * {@link View#onViewTranslationResponse}. * {@link View#onVirtualViewTranslationResponses}. * * @return {@code true} if the View handles hiding the translation. */ Loading
services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java +29 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.translation; 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_STATE; import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE; Loading Loading @@ -192,19 +193,22 @@ final class TranslationManagerServiceImpl extends @GuardedBy("mLock") public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token, ComponentName componentName) { int translationActivityUid = final int translationActivityUid = getActivityUidByComponentName(getContext(), componentName, getUserId()); final String packageName = componentName.getPackageName(); if (activityDestroyed) { // In the Activity destroy case, we only calls onTranslationFinished() in // non-finisTranslation() state. If there is a finisTranslation() calls by apps, we // should remove the waiting callback to avoid callback twice. invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */null, translationActivityUid); invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */ null, packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } else { if (mWaitingFinishedCallbackActivities.contains(token)) { invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */null, translationActivityUid); invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ null, /* targetSpec= */ null, packageName, translationActivityUid); mWaitingFinishedCallbackActivities.remove(token); } } Loading @@ -223,25 +227,25 @@ final class TranslationManagerServiceImpl extends + "state for token=" + token + " taskId=" + taskId + " for state= " + state); return; } mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); if (state == STATE_UI_TRANSLATION_FINISHED) { mWaitingFinishedCallbackActivities.add(token); } int translationActivityUid = -1; try { IBinder activityToken = taskTopActivityTokens.getActivityToken(); try { taskTopActivityTokens.getApplicationThread().updateUiTranslationState( activityToken, state, sourceSpec, targetSpec, viewIds, uiTranslationSpec); mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken); translationActivityUid = getActivityUidByComponentName(getContext(), componentName, getUserId()); } catch (RemoteException 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) { invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid); invokeCallbacks(state, sourceSpec, targetSpec, componentName.getPackageName(), translationActivityUid); } } Loading @@ -266,20 +270,24 @@ final class TranslationManagerServiceImpl extends pw.println(prefix + "Got a RemoteException while dumping the activity"); } } else { pw.print(prefix); pw.println("No requested UiTranslation Activity."); pw.print(prefix); pw.println("No requested UiTranslation Activity."); } final int waitingFinishCallbackSize = mWaitingFinishedCallbackActivities.size(); 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); 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( int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName, int translationActivityUid) { Bundle res = new Bundle(); res.putInt(EXTRA_STATE, state); Loading @@ -288,6 +296,7 @@ final class TranslationManagerServiceImpl extends res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale()); res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale()); } res.putString(EXTRA_PACKAGE_NAME, packageName); // TODO(177500482): Only support the *current* Input Method. List<InputMethodInfo> enabledInputMethods = LocalServices.getService(InputMethodManagerInternal.class) Loading @@ -299,6 +308,7 @@ final class TranslationManagerServiceImpl extends } catch (RemoteException e) { Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e); } return; } // Code here is non-optimal since it's temporary.. boolean isIme = false; Loading