diff options
| author | 2021-06-28 20:47:25 +0800 | |
|---|---|---|
| committer | 2021-07-01 13:14:54 +0800 | |
| commit | bb612abccdf06da459f458926e02d76e0e666724 (patch) | |
| tree | 8dcbf5408f65a40f00d152e285ed121f3d5d915d | |
| parent | 5ded797ef4b81a39e0ed2b66a4974c066a402390 (diff) | |
Notify onFinished when activity is destroyed.
Bug: 184901144
Test: manual
Test: atest UiTranslationManagerTest
Change-Id: Ife6883b6e4b84ad3994b83683b9dfe3af6df91af
5 files changed, 109 insertions, 13 deletions
diff --git a/core/java/android/view/translation/ITranslationManager.aidl b/core/java/android/view/translation/ITranslationManager.aidl index 5fbf228ec72f..cce0193e75e0 100644 --- a/core/java/android/view/translation/ITranslationManager.aidl +++ b/core/java/android/view/translation/ITranslationManager.aidl @@ -16,6 +16,7 @@ package android.view.translation; +import android.content.ComponentName; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.ResultReceiver; @@ -47,4 +48,6 @@ oneway interface ITranslationManager { void registerUiTranslationStateCallback(in IRemoteCallback callback, int userId); void unregisterUiTranslationStateCallback(in IRemoteCallback callback, int userId); void getServiceSettingsActivity(in IResultReceiver result, int userId); + void onTranslationFinished(boolean activityDestroyed, IBinder token, + in ComponentName componentName, int userId); } diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java index 592993cc3d3e..2c1754550297 100644 --- a/core/java/android/view/translation/UiTranslationController.java +++ b/core/java/android/view/translation/UiTranslationController.java @@ -24,6 +24,7 @@ import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION import android.annotation.NonNull; import android.annotation.WorkerThread; import android.app.Activity; +import android.app.assist.ActivityId; import android.content.Context; import android.os.Build; import android.os.Handler; @@ -161,6 +162,7 @@ public class UiTranslationController { view.setHasTranslationTransientState(false); } }); + notifyTranslationFinished(/* activityDestroyed= */ false); synchronized (mLock) { mViews.clear(); } @@ -175,12 +177,28 @@ public class UiTranslationController { */ public void onActivityDestroyed() { synchronized (mLock) { + if (DEBUG) { + Log.i(TAG, + "onActivityDestroyed(): mCurrentState is " + stateToString(mCurrentState)); + } + if (mCurrentState != STATE_UI_TRANSLATION_FINISHED) { + notifyTranslationFinished(/* activityDestroyed= */ true); + } mViews.clear(); destroyTranslators(); mWorkerThread.quitSafely(); } } + private void notifyTranslationFinished(boolean activityDestroyed) { + UiTranslationManager manager = mContext.getSystemService(UiTranslationManager.class); + if (manager != null) { + manager.onTranslationFinished(activityDestroyed, + new ActivityId(mActivity.getTaskId(), mActivity.getShareableActivityToken()), + mActivity.getComponentName()); + } + } + private void setLastRequestAutofillIdsLocked(List<AutofillId> views) { if (mLastRequestAutofillIds == null) { mLastRequestAutofillIds = new ArraySet<>(); diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index 3350c9310823..b9ed32ce248b 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.assist.ActivityId; +import android.content.ComponentName; import android.content.Context; import android.icu.util.ULocale; import android.os.Binder; @@ -308,6 +309,26 @@ public final class UiTranslationManager { } } + /** + * Notify apps the translation is finished because {@link #finishTranslation(ActivityId)} is + * called or Activity is destroyed. + * + * @param activityDestroyed if the ui translation is finished because of activity destroyed. + * @param activityId the identifier for the Activity which needs ui translation + * @param componentName the ui translated Activity componentName. + * + * @hide + */ + public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId, + ComponentName componentName) { + try { + mService.onTranslationFinished(activityDestroyed, + activityId.getToken(), componentName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @NonNull @GuardedBy("mCallbacks") private final Map<UiTranslationStateCallback, IRemoteCallback> mCallbacks = new ArrayMap<>(); diff --git a/services/translation/java/com/android/server/translation/TranslationManagerService.java b/services/translation/java/com/android/server/translation/TranslationManagerService.java index 41ee6b5d2ea0..27b254a304ff 100644 --- a/services/translation/java/com/android/server/translation/TranslationManagerService.java +++ b/services/translation/java/com/android/server/translation/TranslationManagerService.java @@ -246,6 +246,16 @@ public final class TranslationManagerService } @Override + public void onTranslationFinished(boolean activityDestroyed, IBinder token, + ComponentName componentName, int userId) { + TranslationManagerServiceImpl service; + synchronized (mLock) { + service = getServiceForUserLocked(userId); + service.onTranslationFinishedLocked(activityDestroyed, token, componentName); + } + } + + @Override public void getServiceSettingsActivity(IResultReceiver result, int userId) { final TranslationManagerServiceImpl service; synchronized (mLock) { diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java index 6606fb0f482c..9f4fee8b00ab 100644 --- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java +++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java @@ -20,10 +20,12 @@ import static android.view.translation.TranslationManager.EXTRA_CAPABILITIES; 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; +import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_FINISHED; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; +import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.os.Bundle; @@ -33,6 +35,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.service.translation.TranslationServiceInfo; +import android.util.ArraySet; import android.util.Slog; import android.view.autofill.AutofillId; import android.view.inputmethod.InputMethodInfo; @@ -83,6 +86,7 @@ final class TranslationManagerServiceImpl extends new TranslationServiceRemoteCallback(); private final RemoteCallbackList<IRemoteCallback> mTranslationCapabilityCallbacks = new RemoteCallbackList<>(); + private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet(); protected TranslationManagerServiceImpl( @NonNull TranslationManagerService master, @@ -169,6 +173,41 @@ final class TranslationManagerServiceImpl extends } } + private int getActivityUidByComponentName(Context context, ComponentName componentName, + int userId) { + int translationActivityUid = -1; + try { + if (componentName != null) { + translationActivityUid = context.getPackageManager().getApplicationInfoAsUser( + componentName.getPackageName(), 0, userId).uid; + } + } catch (PackageManager.NameNotFoundException e) { + Slog.d(TAG, "Cannot find packageManager for" + componentName); + } + return translationActivityUid; + } + + @GuardedBy("mLock") + public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token, + ComponentName componentName) { + int translationActivityUid = + getActivityUidByComponentName(getContext(), componentName, getUserId()); + 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); + mWaitingFinishedCallbackActivities.remove(token); + } else { + if (mWaitingFinishedCallbackActivities.contains(token)) { + invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, /* sourceSpec= */ + null, /* targetSpec= */null, translationActivityUid); + mWaitingFinishedCallbackActivities.remove(token); + } + } + } + @GuardedBy("mLock") public void updateUiTranslationStateLocked(@UiTranslationState int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds, @@ -178,10 +217,13 @@ final class TranslationManagerServiceImpl extends mActivityTaskManagerInternal.getTopActivityForTask(taskId); if (taskTopActivityTokens == null || taskTopActivityTokens.getShareableActivityToken() != token) { - Slog.w(TAG, "Unknown activity or it was finished to query for update " - + "translation state for token=" + token + " taskId=" + taskId); + Slog.w(TAG, "Unknown activity or it was finished to query for update translation " + + "state for token=" + token + " taskId=" + taskId + " for state= " + state); return; } + if (state == STATE_UI_TRANSLATION_FINISHED) { + mWaitingFinishedCallbackActivities.add(token); + } int translationActivityUid = -1; try { IBinder activityToken = taskTopActivityTokens.getActivityToken(); @@ -191,19 +233,14 @@ final class TranslationManagerServiceImpl extends mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken); - try { - if (componentName != null) { - translationActivityUid = - getContext().getPackageManager().getApplicationInfoAsUser( - componentName.getPackageName(), 0, getUserId()).uid; - } - } catch (PackageManager.NameNotFoundException e) { - Slog.d(TAG, "Cannot find package for" + componentName); - } + translationActivityUid = + getActivityUidByComponentName(getContext(), componentName, getUserId()); } catch (RemoteException e) { Slog.w(TAG, "Update UiTranslationState fail: " + e); } - invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid); + if (state != STATE_UI_TRANSLATION_FINISHED) { + invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid); + } } @GuardedBy("mLock") @@ -226,6 +263,14 @@ final class TranslationManagerServiceImpl extends } else { 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.println(waitingFinishCallbackSize); + for (IBinder activityToken : mWaitingFinishedCallbackActivities) { + pw.print(prefix); pw.print("activityToken: "); pw.println(activityToken); + } + } } private void invokeCallbacks( @@ -243,7 +288,6 @@ final class TranslationManagerServiceImpl extends LocalServices.getService(InputMethodManagerInternal.class) .getEnabledInputMethodListAsUser(mUserId); mCallbacks.broadcast((callback, uid) -> { - // callback to the application that is translated if registered. if ((int) uid == translationActivityUid) { try { callback.sendResult(res); |