summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joanne Chung <joannechung@google.com> 2021-06-28 20:47:25 +0800
committer Joanne Chung <joannechung@google.com> 2021-07-01 13:14:54 +0800
commitbb612abccdf06da459f458926e02d76e0e666724 (patch)
tree8dcbf5408f65a40f00d152e285ed121f3d5d915d
parent5ded797ef4b81a39e0ed2b66a4974c066a402390 (diff)
Notify onFinished when activity is destroyed.
Bug: 184901144 Test: manual Test: atest UiTranslationManagerTest Change-Id: Ife6883b6e4b84ad3994b83683b9dfe3af6df91af
-rw-r--r--core/java/android/view/translation/ITranslationManager.aidl3
-rw-r--r--core/java/android/view/translation/UiTranslationController.java18
-rw-r--r--core/java/android/view/translation/UiTranslationManager.java21
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerService.java10
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java70
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);