Notify onFinished when activity is destroyed.
Bug: 184901144 Test: manual Test: atest UiTranslationManagerTest Change-Id: Ife6883b6e4b84ad3994b83683b9dfe3af6df91af
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -245,6 +245,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user