Merge "Add APIs that can notify client ui translation state."

This commit is contained in:
TreeHugger Robot
2021-01-20 04:43:54 +00:00
committed by Android (Google) Code Review
8 changed files with 260 additions and 0 deletions

View File

@@ -137,6 +137,7 @@ package android {
field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
field public static final String MANAGE_TIME_AND_ZONE_DETECTION = "android.permission.MANAGE_TIME_AND_ZONE_DETECTION";
field public static final String MANAGE_UI_TRANSLATION = "android.permission.MANAGE_UI_TRANSLATION";
field public static final String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final String MANAGE_USERS = "android.permission.MANAGE_USERS";
field public static final String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
@@ -1947,6 +1948,7 @@ package android.content {
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final String TETHERING_SERVICE = "tethering";
field public static final String TRANSLATION_MANAGER_SERVICE = "transformer";
field public static final String UI_TRANSLATION_SERVICE = "ui_translation";
field public static final String VR_SERVICE = "vrmanager";
field public static final String WIFI_NL80211_SERVICE = "wifinl80211";
field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
@@ -13437,6 +13439,17 @@ package android.view.contentcapture {
}
package android.view.translation {
public final class UiTranslationManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) public void finishTranslation(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) public void pauseTranslation(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) public void resumeTranslation(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION) public void startTranslation(@NonNull android.view.translation.TranslationSpec, @NonNull android.view.translation.TranslationSpec, @NonNull java.util.List<android.view.autofill.AutofillId>, int);
}
}
package android.webkit {
public abstract class CookieManager {

View File

@@ -210,6 +210,7 @@ import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
import android.view.translation.ITranslationManager;
import android.view.translation.TranslationManager;
import android.view.translation.UiTranslationManager;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
@@ -1187,6 +1188,19 @@ public final class SystemServiceRegistry {
return null;
}});
registerService(Context.UI_TRANSLATION_SERVICE, UiTranslationManager.class,
new CachedServiceFetcher<UiTranslationManager>() {
@Override
public UiTranslationManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IBinder b = ServiceManager.getService(Context.TRANSLATION_MANAGER_SERVICE);
ITranslationManager service = ITranslationManager.Stub.asInterface(b);
if (service != null) {
return new UiTranslationManager(ctx.getOuterContext(), service);
}
return null;
}});
registerService(Context.SEARCH_UI_SERVICE, SearchUiManager.class,
new CachedServiceFetcher<SearchUiManager>() {
@Override

View File

@@ -4519,6 +4519,15 @@ public abstract class Context {
@SuppressLint("ServiceName")
public static final String TRANSLATION_MANAGER_SERVICE = "transformer";
/**
* Official published name of the translation service which supports ui translation function.
*
* @hide
* @see #getSystemService(String)
*/
@SystemApi
public static final String UI_TRANSLATION_SERVICE = "ui_translation";
/**
* Used for getting content selections and classifications for task snapshots.
*

View File

@@ -16,10 +16,15 @@
package android.view.translation;
import android.content.ComponentName;
import android.os.IBinder;
import android.service.translation.TranslationRequest;
import android.view.autofill.AutofillId;
import android.view.translation.TranslationSpec;
import com.android.internal.os.IResultReceiver;
import java.util.List;
/**
* Mediator between apps being translated and translation service implementation.
*
@@ -29,4 +34,8 @@ oneway interface ITranslationManager {
void getSupportedLocales(in IResultReceiver receiver, int userId);
void onSessionCreated(in TranslationSpec sourceSpec, in TranslationSpec destSpec,
int sessionId, in IResultReceiver receiver, int userId);
void updateUiTranslationState(int state, in TranslationSpec sourceSpec,
in TranslationSpec destSpec, in List<AutofillId> viewIds, in int taskId,
int userId);
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2020 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.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.RemoteException;
import android.view.View;
import android.view.autofill.AutofillId;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Objects;
/**
* The {@link UiTranslationManager} class provides ways for apps to use the ui translation
* function in framework.
*
* @hide
*/
@SystemApi
public final class UiTranslationManager {
private static final String TAG = "UiTranslationManager";
/**
* The state caller request to disable utranslation,, it is no longer need to ui translation.
*
* @hide
*/
public static final int STATE_UI_TRANSLATION_STARTED = 0;
/**
* The state caller request to pause ui translation, it will switch back to the original text.
*
* @hide
*/
public static final int STATE_UI_TRANSLATION_PAUSED = 1;
/**
* The state caller request to resume the paused ui translation, it will show the translated
* text again if the text had been translated.
*
* @hide
*/
public static final int STATE_UI_TRANSLATION_RESUMED = 2;
/**
* The state the caller request to enable ui translation.
*
* @hide
*/
public static final int STATE_UI_TRANSLATION_FINISHED = 3;
/**
* @hide
*/
@IntDef(prefix = {"STATE__TRANSLATION"}, value = {
STATE_UI_TRANSLATION_STARTED,
STATE_UI_TRANSLATION_PAUSED,
STATE_UI_TRANSLATION_RESUMED,
STATE_UI_TRANSLATION_FINISHED
})
@Retention(RetentionPolicy.SOURCE)
public @interface UiTranslationState {
}
@NonNull
private final Context mContext;
private final ITranslationManager mService;
/**
* @hide
*/
public UiTranslationManager(@NonNull Context context, ITranslationManager service) {
mContext = Objects.requireNonNull(context);
mService = service;
}
/**
* Request ui translation for a given Views.
*
* @param sourceSpec {@link TranslationSpec} for the data to be translated.
* @param destSpec {@link TranslationSpec} for the translated data.
* @param viewIds A list of the {@link View}'s {@link AutofillId} which needs to be translated
* @param taskId the Activity Task id which needs ui translation
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
public void startTranslation(@NonNull TranslationSpec sourceSpec,
@NonNull TranslationSpec destSpec, @NonNull List<AutofillId> viewIds,
int taskId) {
// TODO(b/177789967): Return result code or find a way to notify the status.
// TODO(b/177394471): The is a temparary API, the expected is requestUiTranslation(
// TranslationSpec, TranslationSpec,List<AutofillId>, Binder). We may need more time to
// implement it, use task id as initial version for demo.
Objects.requireNonNull(sourceSpec);
Objects.requireNonNull(destSpec);
Objects.requireNonNull(viewIds);
try {
mService.updateUiTranslationState(STATE_UI_TRANSLATION_STARTED, sourceSpec,
destSpec, viewIds, taskId, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request to disable the ui translation. It will destroy all the {@link Translator}s and no
* longer to show to show the translated text.
*
* @param taskId the Activity Task id which needs ui translation
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
public void finishTranslation(int taskId) {
try {
// TODO(b/177394471): The is a temparary API, the expected is finishUiTranslation(
// Binder). We may need more time to implement it, use task id as initial version.
mService.updateUiTranslationState(STATE_UI_TRANSLATION_FINISHED,
null /* sourceSpec */, null /* destSpec*/, null /* viewIds */, taskId,
mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request to pause the current ui translation's {@link Translator} which will switch back to
* the original language.
*
* @param taskId the Activity Task id which needs ui translation
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
public void pauseTranslation(int taskId) {
try {
// TODO(b/177394471): The is a temparary API, the expected is pauseUiTranslation(Binder)
// We may need more time to implement it, use task id as initial version for demo
mService.updateUiTranslationState(STATE_UI_TRANSLATION_PAUSED,
null /* sourceSpec */, null /* destSpec*/, null /* viewIds */, taskId,
mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request to resume the paused ui translation's {@link Translator} which will switch to the
* translated language if the text had been translated.
*
* @param taskId the Activity Task id which needs ui translation
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
public void resumeTranslation(int taskId) {
try {
// TODO(b/177394471): The is a temparary API, the expected is resumeUiTranslation(
// Binder). We may need more time to implement it, use task id as initial version.
mService.updateUiTranslationState(STATE_UI_TRANSLATION_RESUMED,
null /* sourceSpec */, null /* destSpec*/, null /* viewIds */,
taskId, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}

View File

@@ -3620,6 +3620,15 @@
<permission android:name="android.permission.BIND_TRANSLATION_SERVICE"
android:protectionLevel="signature" />
<!-- @SystemApi Allows apps to use ui translation functions.
<p>Protection level: signature|privileged
<p> TODO(b/177703453): Restrict to a specific Role instead of allowing access to any
privileged app.
@hide Not for use by third-party applications.
-->
<permission android:name="android.permission.MANAGE_UI_TRANSLATION"
android:protectionLevel="signature|privileged" />
<!-- Must be required by a android.service.contentsuggestions.ContentSuggestionsService,
to ensure that only the system can bind to it.
@SystemApi @hide This is not a third-party API (intended for OEMs and system apps).

View File

@@ -22,13 +22,17 @@ import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
import android.content.Context;
import android.os.RemoteException;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.translation.ITranslationManager;
import android.view.translation.TranslationSpec;
import android.view.translation.UiTranslationManager.UiTranslationState;
import com.android.internal.os.IResultReceiver;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import java.util.List;
/**
* Entry point service for translation management.
*
@@ -82,6 +86,19 @@ public final class TranslationManagerService
}
}
}
@Override
public void updateUiTranslationState(@UiTranslationState int state,
TranslationSpec sourceSpec, TranslationSpec destSpec, List<AutofillId> viewIds,
int taskId, int userId) {
synchronized (mLock) {
final TranslationManagerServiceImpl service = getServiceForUserLocked(userId);
if (service != null) {
service.updateUiTranslationState(state, sourceSpec, destSpec, viewIds,
taskId);
}
}
}
}
@Override // from SystemService

View File

@@ -26,7 +26,9 @@ import android.content.pm.ServiceInfo;
import android.os.RemoteException;
import android.service.translation.TranslationServiceInfo;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.translation.TranslationSpec;
import android.view.translation.UiTranslationManager.UiTranslationState;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -34,6 +36,7 @@ import com.android.internal.util.SyncResultReceiver;
import com.android.server.infra.AbstractPerUserSystemService;
import java.util.ArrayList;
import java.util.List;
final class TranslationManagerServiceImpl extends
AbstractPerUserSystemService<TranslationManagerServiceImpl, TranslationManagerService> {
@@ -122,4 +125,11 @@ final class TranslationManagerServiceImpl extends
remoteService.onSessionCreated(sourceSpec, destSpec, sessionId, resultReceiver);
}
}
@GuardedBy("mLock")
public void updateUiTranslationState(@UiTranslationState int state,
TranslationSpec sourceSpec, TranslationSpec destSpec, List<AutofillId> viewIds,
int taskId) {
// TODO: implement this in next change
}
}