Merge "Add api to propagating translation capability updates." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
efc7e4c0f0
@@ -52812,6 +52812,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
|
||||
}
|
||||
|
||||
|
||||
@@ -10407,6 +10407,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
|
||||
@@ -275,6 +279,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.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
@@ -41,6 +44,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;
|
||||
|
||||
@@ -308,8 +312,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.
|
||||
@@ -360,4 +362,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;
|
||||
}
|
||||
@@ -221,4 +229,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