Merge "Add APIs that can notify client ui translation state."
This commit is contained in:
committed by
Android (Google) Code Review
commit
3f8337ff57
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
179
core/java/android/view/translation/UiTranslationManager.java
Normal file
179
core/java/android/view/translation/UiTranslationManager.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user