Merge "Notify onFinished when activity is destroyed." into sc-dev
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.view.translation;
|
package android.view.translation;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
@@ -47,4 +48,6 @@ oneway interface ITranslationManager {
|
|||||||
void registerUiTranslationStateCallback(in IRemoteCallback callback, int userId);
|
void registerUiTranslationStateCallback(in IRemoteCallback callback, int userId);
|
||||||
void unregisterUiTranslationStateCallback(in IRemoteCallback callback, int userId);
|
void unregisterUiTranslationStateCallback(in IRemoteCallback callback, int userId);
|
||||||
void getServiceSettingsActivity(in IResultReceiver result, 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.NonNull;
|
||||||
import android.annotation.WorkerThread;
|
import android.annotation.WorkerThread;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.assist.ActivityId;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -161,6 +162,7 @@ public class UiTranslationController {
|
|||||||
view.setHasTranslationTransientState(false);
|
view.setHasTranslationTransientState(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
notifyTranslationFinished(/* activityDestroyed= */ false);
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mViews.clear();
|
mViews.clear();
|
||||||
}
|
}
|
||||||
@@ -175,12 +177,28 @@ public class UiTranslationController {
|
|||||||
*/
|
*/
|
||||||
public void onActivityDestroyed() {
|
public void onActivityDestroyed() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(TAG,
|
||||||
|
"onActivityDestroyed(): mCurrentState is " + stateToString(mCurrentState));
|
||||||
|
}
|
||||||
|
if (mCurrentState != STATE_UI_TRANSLATION_FINISHED) {
|
||||||
|
notifyTranslationFinished(/* activityDestroyed= */ true);
|
||||||
|
}
|
||||||
mViews.clear();
|
mViews.clear();
|
||||||
destroyTranslators();
|
destroyTranslators();
|
||||||
mWorkerThread.quitSafely();
|
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) {
|
private void setLastRequestAutofillIdsLocked(List<AutofillId> views) {
|
||||||
if (mLastRequestAutofillIds == null) {
|
if (mLastRequestAutofillIds == null) {
|
||||||
mLastRequestAutofillIds = new ArraySet<>();
|
mLastRequestAutofillIds = new ArraySet<>();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.app.assist.ActivityId;
|
import android.app.assist.ActivityId;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.icu.util.ULocale;
|
import android.icu.util.ULocale;
|
||||||
import android.os.Binder;
|
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
|
@NonNull
|
||||||
@GuardedBy("mCallbacks")
|
@GuardedBy("mCallbacks")
|
||||||
private final Map<UiTranslationStateCallback, IRemoteCallback> mCallbacks = new ArrayMap<>();
|
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
|
@Override
|
||||||
public void getServiceSettingsActivity(IResultReceiver result, int userId) {
|
public void getServiceSettingsActivity(IResultReceiver result, int userId) {
|
||||||
final TranslationManagerServiceImpl service;
|
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_SOURCE_LOCALE;
|
||||||
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
|
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
|
||||||
import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE;
|
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.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -33,6 +35,7 @@ import android.os.RemoteCallbackList;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.service.translation.TranslationServiceInfo;
|
import android.service.translation.TranslationServiceInfo;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.autofill.AutofillId;
|
import android.view.autofill.AutofillId;
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
@@ -83,6 +86,7 @@ final class TranslationManagerServiceImpl extends
|
|||||||
new TranslationServiceRemoteCallback();
|
new TranslationServiceRemoteCallback();
|
||||||
private final RemoteCallbackList<IRemoteCallback> mTranslationCapabilityCallbacks =
|
private final RemoteCallbackList<IRemoteCallback> mTranslationCapabilityCallbacks =
|
||||||
new RemoteCallbackList<>();
|
new RemoteCallbackList<>();
|
||||||
|
private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet();
|
||||||
|
|
||||||
protected TranslationManagerServiceImpl(
|
protected TranslationManagerServiceImpl(
|
||||||
@NonNull TranslationManagerService master,
|
@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")
|
@GuardedBy("mLock")
|
||||||
public void updateUiTranslationStateLocked(@UiTranslationState int state,
|
public void updateUiTranslationStateLocked(@UiTranslationState int state,
|
||||||
TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds,
|
TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds,
|
||||||
@@ -178,10 +217,13 @@ final class TranslationManagerServiceImpl extends
|
|||||||
mActivityTaskManagerInternal.getTopActivityForTask(taskId);
|
mActivityTaskManagerInternal.getTopActivityForTask(taskId);
|
||||||
if (taskTopActivityTokens == null
|
if (taskTopActivityTokens == null
|
||||||
|| taskTopActivityTokens.getShareableActivityToken() != token) {
|
|| taskTopActivityTokens.getShareableActivityToken() != token) {
|
||||||
Slog.w(TAG, "Unknown activity or it was finished to query for update "
|
Slog.w(TAG, "Unknown activity or it was finished to query for update translation "
|
||||||
+ "translation state for token=" + token + " taskId=" + taskId);
|
+ "state for token=" + token + " taskId=" + taskId + " for state= " + state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (state == STATE_UI_TRANSLATION_FINISHED) {
|
||||||
|
mWaitingFinishedCallbackActivities.add(token);
|
||||||
|
}
|
||||||
int translationActivityUid = -1;
|
int translationActivityUid = -1;
|
||||||
try {
|
try {
|
||||||
IBinder activityToken = taskTopActivityTokens.getActivityToken();
|
IBinder activityToken = taskTopActivityTokens.getActivityToken();
|
||||||
@@ -191,19 +233,14 @@ final class TranslationManagerServiceImpl extends
|
|||||||
mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
|
mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
|
||||||
ComponentName componentName =
|
ComponentName componentName =
|
||||||
mActivityTaskManagerInternal.getActivityName(activityToken);
|
mActivityTaskManagerInternal.getActivityName(activityToken);
|
||||||
try {
|
translationActivityUid =
|
||||||
if (componentName != null) {
|
getActivityUidByComponentName(getContext(), componentName, getUserId());
|
||||||
translationActivityUid =
|
|
||||||
getContext().getPackageManager().getApplicationInfoAsUser(
|
|
||||||
componentName.getPackageName(), 0, getUserId()).uid;
|
|
||||||
}
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
Slog.d(TAG, "Cannot find package for" + componentName);
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "Update UiTranslationState fail: " + 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")
|
@GuardedBy("mLock")
|
||||||
@@ -226,6 +263,14 @@ final class TranslationManagerServiceImpl extends
|
|||||||
} else {
|
} 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.println(waitingFinishCallbackSize);
|
||||||
|
for (IBinder activityToken : mWaitingFinishedCallbackActivities) {
|
||||||
|
pw.print(prefix); pw.print("activityToken: "); pw.println(activityToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeCallbacks(
|
private void invokeCallbacks(
|
||||||
@@ -243,7 +288,6 @@ final class TranslationManagerServiceImpl extends
|
|||||||
LocalServices.getService(InputMethodManagerInternal.class)
|
LocalServices.getService(InputMethodManagerInternal.class)
|
||||||
.getEnabledInputMethodListAsUser(mUserId);
|
.getEnabledInputMethodListAsUser(mUserId);
|
||||||
mCallbacks.broadcast((callback, uid) -> {
|
mCallbacks.broadcast((callback, uid) -> {
|
||||||
// callback to the application that is translated if registered.
|
|
||||||
if ((int) uid == translationActivityUid) {
|
if ((int) uid == translationActivityUid) {
|
||||||
try {
|
try {
|
||||||
callback.sendResult(res);
|
callback.sendResult(res);
|
||||||
|
|||||||
Reference in New Issue
Block a user