Merge changes from topic "b192331240-singleInvoke" into tm-dev
* changes: Rename translationActivityUid to translatedAppUid. Reduce duplicate UiTranslationStateCallback calls.
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac9ae5d960
@@ -25,14 +25,28 @@ import java.util.concurrent.Executor;
|
|||||||
* Callback for listening to UI Translation state changes. See {@link
|
* Callback for listening to UI Translation state changes. See {@link
|
||||||
* UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}.
|
* UiTranslationManager#registerUiTranslationStateCallback(Executor, UiTranslationStateCallback)}.
|
||||||
* <p>
|
* <p>
|
||||||
* Prior to Android version {@link android.os.Build.VERSION_CODES#TIRAMISU}, callback methods
|
* Prior to Android version {@link android.os.Build.VERSION_CODES#TIRAMISU}:
|
||||||
* <em>without</em> {@code packageName} are invoked. Apps with minSdkVersion lower than {@link
|
* <ul>
|
||||||
* android.os.Build.VERSION_CODES#TIRAMISU} <em>must</em> implement those methods if they want to
|
* <li>Callback methods <em>without</em> {@code packageName} are invoked. Apps with
|
||||||
* handle the events.
|
* minSdkVersion lower than {@link android.os.Build.VERSION_CODES#TIRAMISU} <em>must</em>
|
||||||
|
* implement those methods if they want to handle the events.</li>
|
||||||
|
* <li>Callback methods for a particular event <em>may</em> be called multiple times
|
||||||
|
* consecutively, even when the translation state has not changed (e.g.,
|
||||||
|
* {@link #onStarted(ULocale, ULocale, String)} may be called multiple times even after
|
||||||
|
* translation has already started).</li>
|
||||||
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* In Android version {@link android.os.Build.VERSION_CODES#TIRAMISU} and later, if both methods
|
* In Android version {@link android.os.Build.VERSION_CODES#TIRAMISU} and later:
|
||||||
* with and without {@code packageName} are implemented (e.g., {@link #onFinished()} and {@link
|
* <ul>
|
||||||
* #onFinished(String)}, only the one <em>with</em> {@code packageName} will be called.
|
* <li>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.</li>
|
||||||
|
* <li>Callback methods for a particular event will <em>not</em> be called multiple times
|
||||||
|
* consecutively. They will only be called when the translation state has actually changed
|
||||||
|
* (e.g., from "started" to "paused"). Note: "resumed" is not considered a separate state
|
||||||
|
* from "started", so {@link #onResumed(ULocale, ULocale, String)} will never be called after
|
||||||
|
* {@link #onStarted(ULocale, ULocale, String)}.<</li>
|
||||||
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public interface UiTranslationStateCallback {
|
public interface UiTranslationStateCallback {
|
||||||
|
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ 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.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.autofill.AutofillId;
|
import android.view.autofill.AutofillId;
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
import android.view.translation.ITranslationServiceCallback;
|
import android.view.translation.ITranslationServiceCallback;
|
||||||
@@ -71,7 +71,8 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
final class TranslationManagerServiceImpl extends
|
final class TranslationManagerServiceImpl extends
|
||||||
AbstractPerUserSystemService<TranslationManagerServiceImpl, TranslationManagerService> {
|
AbstractPerUserSystemService<TranslationManagerServiceImpl, TranslationManagerService>
|
||||||
|
implements IBinder.DeathRecipient {
|
||||||
|
|
||||||
private static final String TAG = "TranslationManagerServiceImpl";
|
private static final String TAG = "TranslationManagerServiceImpl";
|
||||||
@SuppressLint("IsLoggableTagLength")
|
@SuppressLint("IsLoggableTagLength")
|
||||||
@@ -100,10 +101,10 @@ final class TranslationManagerServiceImpl extends
|
|||||||
private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet<>();
|
private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key is translated activity uid, value is the specification and state for the translation.
|
* Key is translated activity token, value is the specification and state for the translation.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private final SparseArray<ActiveTranslation> mActiveTranslations = new SparseArray<>();
|
private final ArrayMap<IBinder, ActiveTranslation> mActiveTranslations = new ArrayMap<>();
|
||||||
|
|
||||||
protected TranslationManagerServiceImpl(
|
protected TranslationManagerServiceImpl(
|
||||||
@NonNull TranslationManagerService master,
|
@NonNull TranslationManagerService master,
|
||||||
@@ -190,25 +191,24 @@ final class TranslationManagerServiceImpl extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getActivityUidByComponentName(Context context, ComponentName componentName,
|
private int getAppUidByComponentName(Context context, ComponentName componentName, int userId) {
|
||||||
int userId) {
|
int translatedAppUid = -1;
|
||||||
int translationActivityUid = -1;
|
|
||||||
try {
|
try {
|
||||||
if (componentName != null) {
|
if (componentName != null) {
|
||||||
translationActivityUid = context.getPackageManager().getApplicationInfoAsUser(
|
translatedAppUid = context.getPackageManager().getApplicationInfoAsUser(
|
||||||
componentName.getPackageName(), 0, userId).uid;
|
componentName.getPackageName(), 0, userId).uid;
|
||||||
}
|
}
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
Slog.d(TAG, "Cannot find packageManager for" + componentName);
|
Slog.d(TAG, "Cannot find packageManager for" + componentName);
|
||||||
}
|
}
|
||||||
return translationActivityUid;
|
return translatedAppUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token,
|
public void onTranslationFinishedLocked(boolean activityDestroyed, IBinder token,
|
||||||
ComponentName componentName) {
|
ComponentName componentName) {
|
||||||
final int translationActivityUid =
|
final int translatedAppUid =
|
||||||
getActivityUidByComponentName(getContext(), componentName, getUserId());
|
getAppUidByComponentName(getContext(), componentName, getUserId());
|
||||||
final String packageName = componentName.getPackageName();
|
final String packageName = componentName.getPackageName();
|
||||||
if (activityDestroyed) {
|
if (activityDestroyed) {
|
||||||
// In the Activity destroy case, we only calls onTranslationFinished() in
|
// In the Activity destroy case, we only calls onTranslationFinished() in
|
||||||
@@ -216,13 +216,13 @@ final class TranslationManagerServiceImpl extends
|
|||||||
// should remove the waiting callback to avoid callback twice.
|
// should remove the waiting callback to avoid callback twice.
|
||||||
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
|
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
|
||||||
/* sourceSpec= */ null, /* targetSpec= */ null,
|
/* sourceSpec= */ null, /* targetSpec= */ null,
|
||||||
packageName, translationActivityUid);
|
packageName, translatedAppUid);
|
||||||
mWaitingFinishedCallbackActivities.remove(token);
|
mWaitingFinishedCallbackActivities.remove(token);
|
||||||
} else {
|
} else {
|
||||||
if (mWaitingFinishedCallbackActivities.contains(token)) {
|
if (mWaitingFinishedCallbackActivities.contains(token)) {
|
||||||
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
|
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED,
|
||||||
/* sourceSpec= */ null, /* targetSpec= */ null,
|
/* sourceSpec= */ null, /* targetSpec= */ null,
|
||||||
packageName, translationActivityUid);
|
packageName, translatedAppUid);
|
||||||
mWaitingFinishedCallbackActivities.remove(token);
|
mWaitingFinishedCallbackActivities.remove(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,48 +259,161 @@ final class TranslationManagerServiceImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken);
|
ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken);
|
||||||
int translationActivityUid =
|
int translatedAppUid =
|
||||||
getActivityUidByComponentName(getContext(), componentName, getUserId());
|
getAppUidByComponentName(getContext(), componentName, getUserId());
|
||||||
String packageName = componentName.getPackageName();
|
String packageName = componentName.getPackageName();
|
||||||
if (state != STATE_UI_TRANSLATION_FINISHED) {
|
|
||||||
invokeCallbacks(state, sourceSpec, targetSpec, packageName, translationActivityUid);
|
invokeCallbacksIfNecessaryLocked(state, sourceSpec, targetSpec, packageName, activityToken,
|
||||||
updateActiveTranslations(state, sourceSpec, targetSpec, packageName,
|
translatedAppUid);
|
||||||
translationActivityUid);
|
updateActiveTranslationsLocked(state, sourceSpec, targetSpec, packageName, activityToken,
|
||||||
} else {
|
translatedAppUid);
|
||||||
if (mActiveTranslations.contains(translationActivityUid)) {
|
|
||||||
mActiveTranslations.delete(translationActivityUid);
|
|
||||||
} else {
|
|
||||||
Slog.w(TAG, "Finishing translation for activity with uid=" + translationActivityUid
|
|
||||||
+ " but no active translation was found for it");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private void updateActiveTranslationsLocked(int state, TranslationSpec sourceSpec,
|
||||||
|
TranslationSpec targetSpec, String packageName, IBinder activityToken,
|
||||||
|
int translatedAppUid) {
|
||||||
|
// We keep track of active translations and their state so that we can:
|
||||||
|
// 1. Trigger callbacks that are registered after translation has started.
|
||||||
|
// See registerUiTranslationStateCallbackLocked().
|
||||||
|
// 2. NOT trigger callbacks when the state didn't change.
|
||||||
|
// See invokeCallbacksIfNecessaryLocked().
|
||||||
|
ActiveTranslation activeTranslation = mActiveTranslations.get(activityToken);
|
||||||
|
switch (state) {
|
||||||
|
case STATE_UI_TRANSLATION_STARTED: {
|
||||||
|
if (activeTranslation == null) {
|
||||||
|
try {
|
||||||
|
activityToken.linkToDeath(this, /* flags= */ 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Failed to call linkToDeath for translated app with uid="
|
||||||
|
+ translatedAppUid + "; activity is already dead", e);
|
||||||
|
|
||||||
|
// Apps with registered callbacks were just notified that translation
|
||||||
|
// started. We should let them know translation is finished too.
|
||||||
|
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, sourceSpec, targetSpec,
|
||||||
|
packageName, translatedAppUid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mActiveTranslations.put(activityToken,
|
||||||
|
new ActiveTranslation(sourceSpec, targetSpec, translatedAppUid,
|
||||||
|
packageName));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_PAUSED: {
|
||||||
|
if (activeTranslation != null) {
|
||||||
|
activeTranslation.isPaused = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_RESUMED: {
|
||||||
|
if (activeTranslation != null) {
|
||||||
|
activeTranslation.isPaused = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_FINISHED: {
|
||||||
|
if (activeTranslation != null) {
|
||||||
|
mActiveTranslations.remove(activityToken);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG,
|
||||||
|
"Updating to translation state=" + state + " for app with uid="
|
||||||
|
+ translatedAppUid + " packageName=" + packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void updateActiveTranslations(int state, TranslationSpec sourceSpec,
|
private void invokeCallbacksIfNecessaryLocked(int state, TranslationSpec sourceSpec,
|
||||||
TranslationSpec targetSpec, String packageName, int translationActivityUid) {
|
TranslationSpec targetSpec, String packageName, IBinder activityToken,
|
||||||
// Keep track of active translations so that we can trigger callbacks that are
|
int translatedAppUid) {
|
||||||
// registered after translation has started.
|
boolean shouldInvokeCallbacks = true;
|
||||||
switch (state) {
|
int stateForCallbackInvocation = state;
|
||||||
case STATE_UI_TRANSLATION_STARTED: {
|
|
||||||
ActiveTranslation activeTranslation = new ActiveTranslation(sourceSpec,
|
ActiveTranslation activeTranslation = mActiveTranslations.get(activityToken);
|
||||||
targetSpec, packageName);
|
if (activeTranslation == null) {
|
||||||
mActiveTranslations.put(translationActivityUid, activeTranslation);
|
if (state != STATE_UI_TRANSLATION_STARTED) {
|
||||||
break;
|
shouldInvokeCallbacks = false;
|
||||||
}
|
Slog.w(TAG,
|
||||||
case STATE_UI_TRANSLATION_PAUSED:
|
"Updating to translation state=" + state + " for app with uid="
|
||||||
case STATE_UI_TRANSLATION_RESUMED: {
|
+ translatedAppUid + " packageName=" + packageName
|
||||||
ActiveTranslation activeTranslation = mActiveTranslations.get(
|
|
||||||
translationActivityUid);
|
|
||||||
if (activeTranslation != null) {
|
|
||||||
activeTranslation.isPaused = (state == STATE_UI_TRANSLATION_PAUSED);
|
|
||||||
} else {
|
|
||||||
Slog.w(TAG, "Pausing or resuming translation for activity with uid="
|
|
||||||
+ translationActivityUid
|
|
||||||
+ " but no active translation was found for it");
|
+ " but no active translation was found for it");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch (state) {
|
||||||
|
case STATE_UI_TRANSLATION_STARTED: {
|
||||||
|
boolean specsAreIdentical = activeTranslation.sourceSpec.getLocale().equals(
|
||||||
|
sourceSpec.getLocale())
|
||||||
|
&& activeTranslation.targetSpec.getLocale().equals(
|
||||||
|
targetSpec.getLocale());
|
||||||
|
if (specsAreIdentical) {
|
||||||
|
if (activeTranslation.isPaused) {
|
||||||
|
// Ideally UiTranslationManager.resumeTranslation() should be first
|
||||||
|
// used to resume translation, but for the purposes of invoking the
|
||||||
|
// callback, we want to call onResumed() instead of onStarted(). This
|
||||||
|
// way there can only be one call to onStarted() for the lifetime of
|
||||||
|
// a translated activity and this will simplify the number of states
|
||||||
|
// apps have to handle.
|
||||||
|
stateForCallbackInvocation = STATE_UI_TRANSLATION_RESUMED;
|
||||||
|
} else {
|
||||||
|
// Don't invoke callbacks if the state or specs didn't change. For a
|
||||||
|
// given activity, startTranslation() will be called every time there
|
||||||
|
// are new views to be translated, but we don't need to repeatedly
|
||||||
|
// notify apps about it.
|
||||||
|
shouldInvokeCallbacks = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_PAUSED: {
|
||||||
|
if (activeTranslation.isPaused) {
|
||||||
|
// Don't invoke callbacks if the state didn't change.
|
||||||
|
shouldInvokeCallbacks = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_RESUMED: {
|
||||||
|
if (!activeTranslation.isPaused) {
|
||||||
|
// Don't invoke callbacks if the state didn't change. Either
|
||||||
|
// resumeTranslation() was called consecutive times, or right after
|
||||||
|
// startTranslation(). The latter case shouldn't happen normally, so we
|
||||||
|
// don't want apps to have to handle that particular transition.
|
||||||
|
shouldInvokeCallbacks = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_UI_TRANSLATION_FINISHED: {
|
||||||
|
// Note: Here finishTranslation() was called but we don't want to invoke
|
||||||
|
// onFinished() on the callbacks. They will be invoked when
|
||||||
|
// UiTranslationManager.onTranslationFinished() is called (see
|
||||||
|
// onTranslationFinishedLocked()).
|
||||||
|
shouldInvokeCallbacks = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG,
|
||||||
|
(shouldInvokeCallbacks ? "" : "NOT ")
|
||||||
|
+ "Invoking callbacks for translation state="
|
||||||
|
+ stateForCallbackInvocation + " for app with uid=" + translatedAppUid
|
||||||
|
+ " packageName=" + packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldInvokeCallbacks) {
|
||||||
|
invokeCallbacks(stateForCallbackInvocation, sourceSpec, targetSpec, packageName,
|
||||||
|
translatedAppUid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,15 +456,14 @@ final class TranslationManagerServiceImpl extends
|
|||||||
|
|
||||||
private void invokeCallbacks(
|
private void invokeCallbacks(
|
||||||
int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName,
|
int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName,
|
||||||
int translationActivityUid) {
|
int translatedAppUid) {
|
||||||
Bundle result = createResultForCallback(state, sourceSpec, targetSpec, packageName);
|
Bundle result = createResultForCallback(state, sourceSpec, targetSpec, packageName);
|
||||||
if (mCallbacks.getRegisteredCallbackCount() == 0) {
|
if (mCallbacks.getRegisteredCallbackCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
|
List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
|
||||||
mCallbacks.broadcast((callback, uid) -> {
|
mCallbacks.broadcast((callback, uid) -> {
|
||||||
invokeCallback((int) uid, translationActivityUid, callback, result,
|
invokeCallback((int) uid, translatedAppUid, callback, result, enabledInputMethods);
|
||||||
enabledInputMethods);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,9 +486,9 @@ final class TranslationManagerServiceImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void invokeCallback(
|
private void invokeCallback(
|
||||||
int callbackSourceUid, int translationActivityUid, IRemoteCallback callback,
|
int callbackSourceUid, int translatedAppUid, IRemoteCallback callback,
|
||||||
Bundle result, List<InputMethodInfo> enabledInputMethods) {
|
Bundle result, List<InputMethodInfo> enabledInputMethods) {
|
||||||
if (callbackSourceUid == translationActivityUid) {
|
if (callbackSourceUid == translatedAppUid) {
|
||||||
// Invoke callback for the application being translated.
|
// Invoke callback for the application being translated.
|
||||||
try {
|
try {
|
||||||
callback.sendResult(result);
|
callback.sendResult(result);
|
||||||
@@ -417,29 +529,26 @@ final class TranslationManagerServiceImpl extends
|
|||||||
// Trigger the callback for already active translations.
|
// Trigger the callback for already active translations.
|
||||||
List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
|
List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
|
||||||
for (int i = 0; i < mActiveTranslations.size(); i++) {
|
for (int i = 0; i < mActiveTranslations.size(); i++) {
|
||||||
int activeTranslationUid = mActiveTranslations.keyAt(i);
|
|
||||||
ActiveTranslation activeTranslation = mActiveTranslations.valueAt(i);
|
ActiveTranslation activeTranslation = mActiveTranslations.valueAt(i);
|
||||||
if (activeTranslation == null) {
|
int translatedAppUid = activeTranslation.translatedAppUid;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String packageName = activeTranslation.packageName;
|
String packageName = activeTranslation.packageName;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Triggering callback for sourceUid=" + sourceUid
|
Slog.d(TAG, "Triggering callback for sourceUid=" + sourceUid
|
||||||
+ " for translated activity with uid=" + activeTranslationUid
|
+ " for translated app with uid=" + translatedAppUid
|
||||||
+ "packageName=" + packageName + " isPaused=" + activeTranslation.isPaused);
|
+ "packageName=" + packageName + " isPaused=" + activeTranslation.isPaused);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bundle startedResult = createResultForCallback(STATE_UI_TRANSLATION_STARTED,
|
Bundle startedResult = createResultForCallback(STATE_UI_TRANSLATION_STARTED,
|
||||||
activeTranslation.sourceSpec, activeTranslation.targetSpec,
|
activeTranslation.sourceSpec, activeTranslation.targetSpec,
|
||||||
packageName);
|
packageName);
|
||||||
invokeCallback(sourceUid, activeTranslationUid, callback, startedResult,
|
invokeCallback(sourceUid, translatedAppUid, callback, startedResult,
|
||||||
enabledInputMethods);
|
enabledInputMethods);
|
||||||
if (activeTranslation.isPaused) {
|
if (activeTranslation.isPaused) {
|
||||||
// Also send event so callback owners know that translation was started then paused.
|
// Also send event so callback owners know that translation was started then paused.
|
||||||
Bundle pausedResult = createResultForCallback(STATE_UI_TRANSLATION_PAUSED,
|
Bundle pausedResult = createResultForCallback(STATE_UI_TRANSLATION_PAUSED,
|
||||||
activeTranslation.sourceSpec, activeTranslation.targetSpec,
|
activeTranslation.sourceSpec, activeTranslation.targetSpec,
|
||||||
packageName);
|
packageName);
|
||||||
invokeCallback(sourceUid, activeTranslationUid, callback, pausedResult,
|
invokeCallback(sourceUid, translatedAppUid, callback, pausedResult,
|
||||||
enabledInputMethods);
|
enabledInputMethods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,13 +601,34 @@ final class TranslationManagerServiceImpl extends
|
|||||||
public final TranslationSpec sourceSpec;
|
public final TranslationSpec sourceSpec;
|
||||||
public final TranslationSpec targetSpec;
|
public final TranslationSpec targetSpec;
|
||||||
public final String packageName;
|
public final String packageName;
|
||||||
|
public final int translatedAppUid;
|
||||||
public boolean isPaused = false;
|
public boolean isPaused = false;
|
||||||
|
|
||||||
private ActiveTranslation(TranslationSpec sourceSpec, TranslationSpec targetSpec,
|
private ActiveTranslation(TranslationSpec sourceSpec, TranslationSpec targetSpec,
|
||||||
String packageName) {
|
int translatedAppUid, String packageName) {
|
||||||
this.sourceSpec = sourceSpec;
|
this.sourceSpec = sourceSpec;
|
||||||
this.targetSpec = targetSpec;
|
this.targetSpec = targetSpec;
|
||||||
|
this.translatedAppUid = translatedAppUid;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
// Don't need to implement this with binderDied(IBinder) implemented.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied(IBinder who) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mWaitingFinishedCallbackActivities.remove(who);
|
||||||
|
ActiveTranslation activeTranslation = mActiveTranslations.remove(who);
|
||||||
|
if (activeTranslation != null) {
|
||||||
|
// Let apps with registered callbacks know about the activity's death.
|
||||||
|
invokeCallbacks(STATE_UI_TRANSLATION_FINISHED, activeTranslation.sourceSpec,
|
||||||
|
activeTranslation.targetSpec, activeTranslation.packageName,
|
||||||
|
activeTranslation.translatedAppUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user