Add api to propagating translation capability updates.
This change adda the apia in the TranslationService that allows to update the TranslationCapability to the registered clients. This change doesn't contain the register part in the TranslationManager, the change will be done on the next change. Bug: 176208267 Test: atest CtsTranslationTestCases Test: manual verification CTS-Coverage-Bug: 182990474 Change-Id: Iec7b3dc30f99985415162394d0e64d8e825ea5d9
This commit is contained in:
@@ -52771,6 +52771,7 @@ package android.view.translation {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.translation.TranslationCapability> CREATOR;
|
||||
field public static final int STATE_AVAILABLE_TO_DOWNLOAD = 1; // 0x1
|
||||
field public static final int STATE_DOWNLOADING = 2; // 0x2
|
||||
field public static final int STATE_NOT_AVAILABLE = 4; // 0x4
|
||||
field public static final int STATE_ON_DEVICE = 3; // 0x3
|
||||
}
|
||||
|
||||
|
||||
@@ -10405,6 +10405,7 @@ package android.service.translation {
|
||||
method public abstract void onFinishTranslationSession(int);
|
||||
method public abstract void onTranslationCapabilitiesRequest(int, int, @NonNull java.util.function.Consumer<java.util.Set<android.view.translation.TranslationCapability>>);
|
||||
method public abstract void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull android.service.translation.TranslationService.OnTranslationResultCallback);
|
||||
method public final void updateTranslationCapability(@NonNull android.view.translation.TranslationCapability);
|
||||
field public static final String SERVICE_INTERFACE = "android.service.translation.TranslationService";
|
||||
field public static final String SERVICE_META_DATA = "android.translation_service";
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.service.translation;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.view.translation.TranslationContext;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
@@ -30,7 +31,7 @@ import com.android.internal.os.IResultReceiver;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITranslationService {
|
||||
void onConnected();
|
||||
void onConnected(in IBinder callback);
|
||||
void onDisconnected();
|
||||
void onCreateTranslationSession(in TranslationContext translationContext, int sessionId,
|
||||
in IResultReceiver receiver);
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.os.ResultReceiver;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.translation.ITranslationDirectManager;
|
||||
import android.view.translation.ITranslationServiceCallback;
|
||||
import android.view.translation.TranslationCapability;
|
||||
import android.view.translation.TranslationContext;
|
||||
import android.view.translation.TranslationManager;
|
||||
@@ -50,6 +51,7 @@ import android.view.translation.TranslationSpec;
|
||||
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -84,15 +86,17 @@ public abstract class TranslationService extends Service {
|
||||
public static final String SERVICE_META_DATA = "android.translation_service";
|
||||
|
||||
private Handler mHandler;
|
||||
private ITranslationServiceCallback mCallback;
|
||||
|
||||
|
||||
/**
|
||||
* Binder to receive calls from system server.
|
||||
*/
|
||||
private final ITranslationService mInterface = new ITranslationService.Stub() {
|
||||
@Override
|
||||
public void onConnected() {
|
||||
mHandler.sendMessage(obtainMessage(TranslationService::onConnected,
|
||||
TranslationService.this));
|
||||
public void onConnected(IBinder callback) {
|
||||
mHandler.sendMessage(obtainMessage(TranslationService::handleOnConnected,
|
||||
TranslationService.this, callback));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -273,6 +277,32 @@ public abstract class TranslationService extends Service {
|
||||
@TranslationSpec.DataFormat int targetFormat,
|
||||
@NonNull Consumer<Set<TranslationCapability>> callback);
|
||||
|
||||
/**
|
||||
* Called by the service to notify an update in existing {@link TranslationCapability}s.
|
||||
*
|
||||
* @param capability the updated {@link TranslationCapability} with its new states and flags.
|
||||
*/
|
||||
public final void updateTranslationCapability(@NonNull TranslationCapability capability) {
|
||||
Objects.requireNonNull(capability, "translation capability should not be null");
|
||||
|
||||
final ITranslationServiceCallback callback = mCallback;
|
||||
if (callback == null) {
|
||||
Log.w(TAG, "updateTranslationCapability(): no server callback");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
callback.updateTranslationCapability(capability);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleOnConnected(@NonNull IBinder callback) {
|
||||
mCallback = ITranslationServiceCallback.Stub.asInterface(callback);
|
||||
onConnected();
|
||||
}
|
||||
|
||||
// TODO(b/176464808): Need to handle client dying case
|
||||
|
||||
private void handleOnCreateTranslationSession(@NonNull TranslationContext translationContext,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view.translation;
|
||||
|
||||
import android.view.translation.TranslationCapability;
|
||||
|
||||
/**
|
||||
* Interface from the Translation service to the system.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITranslationServiceCallback {
|
||||
void updateTranslationCapability(in TranslationCapability capability);
|
||||
}
|
||||
@@ -48,6 +48,16 @@ public final class TranslationCapability implements Parcelable {
|
||||
* TODO: fill in javadoc
|
||||
*/
|
||||
public static final @ModelState int STATE_ON_DEVICE = 3;
|
||||
/**
|
||||
* The translation service does not support translation between the source and target specs.
|
||||
*
|
||||
* <p>Note: This state is not returned from calling
|
||||
* {@link TranslationManager#getOnDeviceTranslationCapabilities}. This state will only appear as
|
||||
* part of capability updates from
|
||||
* {@link TranslationManager#addOnDeviceTranslationCapabilityUpdateListener} if existing support
|
||||
* was dropped.</p>
|
||||
*/
|
||||
public static final @ModelState int STATE_NOT_AVAILABLE = 4;
|
||||
|
||||
/**
|
||||
* The state of translation readiness between {@code mSourceSpec} and {@code mTargetSpec}.
|
||||
@@ -103,7 +113,7 @@ public final class TranslationCapability implements Parcelable {
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.22.
|
||||
// Code below generated by codegen v1.0.23.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
@@ -120,7 +130,8 @@ public final class TranslationCapability implements Parcelable {
|
||||
@IntDef(prefix = "STATE_", value = {
|
||||
STATE_AVAILABLE_TO_DOWNLOAD,
|
||||
STATE_DOWNLOADING,
|
||||
STATE_ON_DEVICE
|
||||
STATE_ON_DEVICE,
|
||||
STATE_NOT_AVAILABLE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@DataClass.Generated.Member
|
||||
@@ -136,6 +147,8 @@ public final class TranslationCapability implements Parcelable {
|
||||
return "STATE_DOWNLOADING";
|
||||
case STATE_ON_DEVICE:
|
||||
return "STATE_ON_DEVICE";
|
||||
case STATE_NOT_AVAILABLE:
|
||||
return "STATE_NOT_AVAILABLE";
|
||||
default: return Integer.toHexString(value);
|
||||
}
|
||||
}
|
||||
@@ -238,12 +251,14 @@ public final class TranslationCapability implements Parcelable {
|
||||
|
||||
if (!(mState == STATE_AVAILABLE_TO_DOWNLOAD)
|
||||
&& !(mState == STATE_DOWNLOADING)
|
||||
&& !(mState == STATE_ON_DEVICE)) {
|
||||
&& !(mState == STATE_ON_DEVICE)
|
||||
&& !(mState == STATE_NOT_AVAILABLE)) {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"state was " + mState + " but must be one of: "
|
||||
+ "STATE_AVAILABLE_TO_DOWNLOAD(" + STATE_AVAILABLE_TO_DOWNLOAD + "), "
|
||||
+ "STATE_DOWNLOADING(" + STATE_DOWNLOADING + "), "
|
||||
+ "STATE_ON_DEVICE(" + STATE_ON_DEVICE + ")");
|
||||
+ "STATE_ON_DEVICE(" + STATE_ON_DEVICE + "), "
|
||||
+ "STATE_NOT_AVAILABLE(" + STATE_NOT_AVAILABLE + ")");
|
||||
}
|
||||
|
||||
this.mSourceSpec = sourceSpec;
|
||||
@@ -275,10 +290,10 @@ public final class TranslationCapability implements Parcelable {
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1616438309593L,
|
||||
codegenVersion = "1.0.22",
|
||||
time = 1619119609557L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/core/java/android/view/translation/TranslationCapability.java",
|
||||
inputSignatures = "public static final @android.view.translation.TranslationCapability.ModelState int STATE_AVAILABLE_TO_DOWNLOAD\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_DOWNLOADING\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_ON_DEVICE\nprivate final @android.view.translation.TranslationCapability.ModelState int mState\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final boolean mUiTranslationEnabled\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mSupportedTranslationFlags\nclass TranslationCapability extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genConstructor=false)")
|
||||
inputSignatures = "public static final @android.view.translation.TranslationCapability.ModelState int STATE_AVAILABLE_TO_DOWNLOAD\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_DOWNLOADING\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_ON_DEVICE\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_NOT_AVAILABLE\nprivate final @android.view.translation.TranslationCapability.ModelState int mState\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final boolean mUiTranslationEnabled\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mSupportedTranslationFlags\nclass TranslationCapability extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genConstructor=false)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@ import android.annotation.SystemService;
|
||||
import android.annotation.WorkerThread;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SynchronousResultReceiver;
|
||||
@@ -40,6 +43,7 @@ import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -301,8 +305,6 @@ public final class TranslationManager {
|
||||
sourceFormat, targetFormat, pendingIntent);
|
||||
}
|
||||
|
||||
//TODO: Add method to propagate updates to mTCapabilityUpdateListeners
|
||||
|
||||
/**
|
||||
* Returns an immutable PendingIntent which can be used to launch an activity to view/edit
|
||||
* on-device translation settings.
|
||||
@@ -353,4 +355,25 @@ public final class TranslationManager {
|
||||
return sAvailableRequestId;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TranslationCapabilityRemoteCallback extends
|
||||
IRemoteCallback.Stub {
|
||||
private final Executor mExecutor;
|
||||
|
||||
TranslationCapabilityRemoteCallback(Executor executor) {
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResult(Bundle bundle) {
|
||||
Binder.withCleanCallingIdentity(
|
||||
() -> mExecutor.execute(() -> onTranslationCapabilityUpdate(bundle)));
|
||||
}
|
||||
|
||||
private void onTranslationCapabilityUpdate(Bundle bundle) {
|
||||
TranslationCapability capability = (TranslationCapability) bundle.getParcelable(
|
||||
EXTRA_CAPABILITIES);
|
||||
//TODO: Implement after deciding how capability listeners are implemented.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.service.translation.ITranslationService;
|
||||
import android.service.translation.TranslationService;
|
||||
@@ -44,8 +45,10 @@ final class RemoteTranslationService extends ServiceConnector.Impl<ITranslationS
|
||||
private final int mRequestTimeoutMs;
|
||||
private final ComponentName mComponentName;
|
||||
|
||||
private final IBinder mRemoteCallback;
|
||||
|
||||
RemoteTranslationService(Context context, ComponentName serviceName,
|
||||
int userId, boolean bindInstantServiceAllowed) {
|
||||
int userId, boolean bindInstantServiceAllowed, IBinder callback) {
|
||||
super(context,
|
||||
new Intent(TranslationService.SERVICE_INTERFACE).setComponent(serviceName),
|
||||
bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
|
||||
@@ -53,7 +56,7 @@ final class RemoteTranslationService extends ServiceConnector.Impl<ITranslationS
|
||||
mIdleUnbindTimeoutMs = TIMEOUT_IDLE_UNBIND_MS;
|
||||
mRequestTimeoutMs = TIMEOUT_REQUEST_MS;
|
||||
mComponentName = serviceName;
|
||||
|
||||
mRemoteCallback = callback;
|
||||
// Bind right away.
|
||||
connect();
|
||||
}
|
||||
@@ -67,7 +70,7 @@ final class RemoteTranslationService extends ServiceConnector.Impl<ITranslationS
|
||||
boolean connected) {
|
||||
try {
|
||||
if (connected) {
|
||||
service.onConnected();
|
||||
service.onConnected(mRemoteCallback);
|
||||
} else {
|
||||
service.onDisconnected();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.translation;
|
||||
|
||||
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;
|
||||
@@ -35,6 +36,8 @@ import android.service.translation.TranslationServiceInfo;
|
||||
import android.util.Slog;
|
||||
import android.view.autofill.AutofillId;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.translation.ITranslationServiceCallback;
|
||||
import android.view.translation.TranslationCapability;
|
||||
import android.view.translation.TranslationContext;
|
||||
import android.view.translation.TranslationSpec;
|
||||
import android.view.translation.UiTranslationManager.UiTranslationState;
|
||||
@@ -67,6 +70,11 @@ final class TranslationManagerServiceImpl extends
|
||||
|
||||
private ActivityTaskManagerInternal mActivityTaskManagerInternal;
|
||||
|
||||
private final TranslationServiceRemoteCallback mRemoteServiceCallback =
|
||||
new TranslationServiceRemoteCallback();
|
||||
private final RemoteCallbackList<IRemoteCallback> mTranslationCapabilityCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
protected TranslationManagerServiceImpl(
|
||||
@NonNull TranslationManagerService master,
|
||||
@NonNull Object lock, int userId, boolean disabled) {
|
||||
@@ -117,8 +125,8 @@ final class TranslationManagerServiceImpl extends
|
||||
return null;
|
||||
}
|
||||
final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
|
||||
mRemoteTranslationService = new RemoteTranslationService(getContext(),
|
||||
serviceComponent, mUserId, /* isInstantAllowed= */ false);
|
||||
mRemoteTranslationService = new RemoteTranslationService(getContext(), serviceComponent,
|
||||
mUserId, /* isInstantAllowed= */ false, mRemoteServiceCallback);
|
||||
}
|
||||
return mRemoteTranslationService;
|
||||
}
|
||||
@@ -242,4 +250,29 @@ final class TranslationManagerServiceImpl extends
|
||||
final String packageName = mTranslationServiceInfo.getServiceInfo().packageName;
|
||||
return new ComponentName(packageName, activityName);
|
||||
}
|
||||
|
||||
private void notifyClientsTranslationCapability(TranslationCapability capability) {
|
||||
final Bundle res = new Bundle();
|
||||
res.putParcelable(EXTRA_CAPABILITIES, capability);
|
||||
mTranslationCapabilityCallbacks.broadcast((callback, uid) -> {
|
||||
try {
|
||||
callback.sendResult(res);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final class TranslationServiceRemoteCallback extends
|
||||
ITranslationServiceCallback.Stub {
|
||||
|
||||
@Override
|
||||
public void updateTranslationCapability(TranslationCapability capability) {
|
||||
if (capability == null) {
|
||||
Slog.wtf(TAG, "received a null TranslationCapability from TranslationService.");
|
||||
return;
|
||||
}
|
||||
notifyClientsTranslationCapability(capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user