Merge "Don't cache created Translators in TranslationManager." into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a88f5b74f2
@@ -33,9 +33,9 @@ import android.os.RemoteException;
|
|||||||
import android.os.SynchronousResultReceiver;
|
import android.os.SynchronousResultReceiver;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.IntArray;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.SyncResultReceiver;
|
import com.android.internal.util.SyncResultReceiver;
|
||||||
@@ -102,12 +102,7 @@ public final class TranslationManager {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private final SparseArray<Translator> mTranslators = new SparseArray<>();
|
private final IntArray mTranslatorIds = new IntArray();
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
private final ArrayMap<TranslationContext, Integer> mTranslatorIds =
|
|
||||||
new ArrayMap<>();
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
@@ -127,6 +122,12 @@ public final class TranslationManager {
|
|||||||
/**
|
/**
|
||||||
* Creates an on-device Translator for natural language translation.
|
* Creates an on-device Translator for natural language translation.
|
||||||
*
|
*
|
||||||
|
* <p>In Android 12, this method provided the same cached Translator object when given the
|
||||||
|
* same TranslationContext object. Do not use a Translator destroyed elsewhere as this will
|
||||||
|
* cause an exception on Android 12.
|
||||||
|
*
|
||||||
|
* <p>In later versions, this method never returns a cached Translator.
|
||||||
|
*
|
||||||
* @param translationContext {@link TranslationContext} containing the specs for creating the
|
* @param translationContext {@link TranslationContext} containing the specs for creating the
|
||||||
* Translator.
|
* Translator.
|
||||||
* @param executor Executor to run callback operations
|
* @param executor Executor to run callback operations
|
||||||
@@ -140,45 +141,25 @@ public final class TranslationManager {
|
|||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
Objects.requireNonNull(callback, "callback cannot be null");
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// TODO(b/176464808): Disallow multiple Translator now, it will throw
|
|
||||||
// IllegalStateException. Need to discuss if we can allow multiple Translators.
|
|
||||||
if (mTranslatorIds.containsKey(translationContext)) {
|
|
||||||
executor.execute(() -> callback.accept(
|
|
||||||
mTranslators.get(mTranslatorIds.get(translationContext))));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int translatorId;
|
int translatorId;
|
||||||
do {
|
do {
|
||||||
translatorId = Math.abs(ID_GENERATOR.nextInt());
|
translatorId = Math.abs(ID_GENERATOR.nextInt());
|
||||||
} while (translatorId == 0 || mTranslators.indexOfKey(translatorId) >= 0);
|
} while (translatorId == 0 || mTranslatorIds.indexOf(translatorId) >= 0);
|
||||||
final int tId = translatorId;
|
final int tId = translatorId;
|
||||||
|
|
||||||
new Translator(mContext, translationContext, translatorId, this, mHandler, mService,
|
new Translator(mContext, translationContext, tId, this, mHandler, mService,
|
||||||
new Consumer<Translator>() {
|
translator -> {
|
||||||
@Override
|
if (translator == null) {
|
||||||
public void accept(Translator translator) {
|
Binder.withCleanCallingIdentity(
|
||||||
if (translator == null) {
|
() -> executor.execute(() -> callback.accept(null)));
|
||||||
final long token = Binder.clearCallingIdentity();
|
return;
|
||||||
try {
|
|
||||||
executor.execute(() -> callback.accept(null));
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(token);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mLock) {
|
|
||||||
mTranslators.put(tId, translator);
|
|
||||||
mTranslatorIds.put(translationContext, tId);
|
|
||||||
}
|
|
||||||
final long token = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
executor.execute(() -> callback.accept(translator));
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
mTranslatorIds.add(tId);
|
||||||
|
}
|
||||||
|
Binder.withCleanCallingIdentity(
|
||||||
|
() -> executor.execute(() -> callback.accept(translator)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,16 +182,10 @@ public final class TranslationManager {
|
|||||||
Objects.requireNonNull(translationContext, "translationContext cannot be null");
|
Objects.requireNonNull(translationContext, "translationContext cannot be null");
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// TODO(b/176464808): Disallow multiple Translator now, it will throw
|
|
||||||
// IllegalStateException. Need to discuss if we can allow multiple Translators.
|
|
||||||
if (mTranslatorIds.containsKey(translationContext)) {
|
|
||||||
return mTranslators.get(mTranslatorIds.get(translationContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
int translatorId;
|
int translatorId;
|
||||||
do {
|
do {
|
||||||
translatorId = Math.abs(ID_GENERATOR.nextInt());
|
translatorId = Math.abs(ID_GENERATOR.nextInt());
|
||||||
} while (translatorId == 0 || mTranslators.indexOfKey(translatorId) >= 0);
|
} while (translatorId == 0 || mTranslatorIds.indexOf(translatorId) >= 0);
|
||||||
|
|
||||||
final Translator newTranslator = new Translator(mContext, translationContext,
|
final Translator newTranslator = new Translator(mContext, translationContext,
|
||||||
translatorId, this, mHandler, mService);
|
translatorId, this, mHandler, mService);
|
||||||
@@ -220,8 +195,7 @@ public final class TranslationManager {
|
|||||||
if (!newTranslator.isSessionCreated()) {
|
if (!newTranslator.isSessionCreated()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
mTranslators.put(translatorId, newTranslator);
|
mTranslatorIds.add(translatorId);
|
||||||
mTranslatorIds.put(translationContext, translatorId);
|
|
||||||
return newTranslator;
|
return newTranslator;
|
||||||
} catch (Translator.ServiceBinderReceiver.TimeoutException e) {
|
} catch (Translator.ServiceBinderReceiver.TimeoutException e) {
|
||||||
// TODO(b/176464808): maybe make SyncResultReceiver.TimeoutException constructor
|
// TODO(b/176464808): maybe make SyncResultReceiver.TimeoutException constructor
|
||||||
@@ -460,12 +434,9 @@ public final class TranslationManager {
|
|||||||
|
|
||||||
void removeTranslator(int id) {
|
void removeTranslator(int id) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mTranslators.remove(id);
|
int index = mTranslatorIds.indexOf(id);
|
||||||
for (int i = 0; i < mTranslatorIds.size(); i++) {
|
if (index >= 0) {
|
||||||
if (mTranslatorIds.valueAt(i) == id) {
|
mTranslatorIds.remove(index);
|
||||||
mTranslatorIds.removeAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user