Add system captions manager service
This service connects to a remote system captions manager service. This service is responsible for enabling system captions when the user requests them. As the system binds to it, this service will be persistent. Bug: 128925852 Test: Manual. I created an implementation of the service. Change-Id: Iafde1bb68f4754d8167624f47c6833d43c0ec336
This commit is contained in:
@@ -3564,6 +3564,12 @@
|
||||
-->
|
||||
<string name="config_defaultSystemCaptionsService" translatable="false"></string>
|
||||
|
||||
<!-- The component name for the system-wide captions manager service.
|
||||
This service must be trusted, as the system binds to it and keeps it running.
|
||||
Example: "com.android.captions/.SystemCaptionsManagerService"
|
||||
-->
|
||||
<string name="config_defaultSystemCaptionsManagerService" translatable="false"></string>
|
||||
|
||||
<!-- The package name for the incident report approver app.
|
||||
This app is usually PermissionController or an app that replaces it. When
|
||||
a bugreport or incident report with EXPLICT-level sharing flags is going to be
|
||||
|
||||
@@ -3411,6 +3411,7 @@
|
||||
<java-symbol type="string" name="config_defaultContentSuggestionsService" />
|
||||
<java-symbol type="string" name="config_defaultAttentionService" />
|
||||
<java-symbol type="string" name="config_defaultSystemCaptionsService" />
|
||||
<java-symbol type="string" name="config_defaultSystemCaptionsManagerService" />
|
||||
|
||||
<java-symbol type="string" name="notification_channel_foreground_service" />
|
||||
<java-symbol type="string" name="foreground_service_app_in_background" />
|
||||
|
||||
@@ -31,6 +31,7 @@ java_library {
|
||||
"services.print",
|
||||
"services.restrictions",
|
||||
"services.startop",
|
||||
"services.systemcaptions",
|
||||
"services.usage",
|
||||
"services.usb",
|
||||
"services.voiceinteraction",
|
||||
|
||||
@@ -129,7 +129,8 @@ public final class ContentCaptureManagerService extends
|
||||
public ContentCaptureManagerService(@NonNull Context context) {
|
||||
super(context, new FrameworkResourcesServiceNameResolver(context,
|
||||
com.android.internal.R.string.config_defaultContentCaptureService),
|
||||
UserManager.DISALLOW_CONTENT_CAPTURE, /* refreshServiceOnPackageUpdate= */ false);
|
||||
UserManager.DISALLOW_CONTENT_CAPTURE,
|
||||
/*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_NO_REFRESH);
|
||||
DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
|
||||
ActivityThread.currentApplication().getMainExecutor(),
|
||||
(namespace, key, value) -> onDeviceConfigChange(key, value));
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.server.infra;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
@@ -45,6 +46,8 @@ import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -75,6 +78,30 @@ import java.util.List;
|
||||
public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>,
|
||||
S extends AbstractPerUserSystemService<S, M>> extends SystemService {
|
||||
|
||||
/** On a package update, does not refresh the per-user service in the cache. */
|
||||
public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0;
|
||||
|
||||
/**
|
||||
* On a package update, removes any existing per-user services in the cache.
|
||||
*
|
||||
* <p>This does not immediately recreate these services. It is assumed they will be recreated
|
||||
* for the next user request.
|
||||
*/
|
||||
public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1;
|
||||
|
||||
/**
|
||||
* On a package update, removes and recreates any existing per-user services in the cache.
|
||||
*/
|
||||
public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2;
|
||||
|
||||
@IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = {
|
||||
PACKAGE_UPDATE_POLICY_NO_REFRESH,
|
||||
PACKAGE_UPDATE_POLICY_REFRESH_LAZY,
|
||||
PACKAGE_UPDATE_POLICY_REFRESH_EAGER
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface PackageUpdatePolicy {}
|
||||
|
||||
/**
|
||||
* Log tag
|
||||
*/
|
||||
@@ -127,8 +154,11 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
|
||||
/**
|
||||
* Whether the per-user service should be removed from the cache when its apk is updated.
|
||||
*
|
||||
* <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
|
||||
* {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}.
|
||||
*/
|
||||
private final boolean mRefreshServiceOnPackageUpdate;
|
||||
private final @PackageUpdatePolicy int mPackageUpdatePolicy;
|
||||
|
||||
/**
|
||||
* Name of the service packages whose APK are being updated, keyed by user id.
|
||||
@@ -154,7 +184,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
@Nullable ServiceNameResolver serviceNameResolver,
|
||||
@Nullable String disallowProperty) {
|
||||
this(context, serviceNameResolver, disallowProperty,
|
||||
/* refreshServiceOnPackageUpdate=*/ true);
|
||||
/*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,17 +197,19 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
* @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
|
||||
* disables the service. <b>NOTE: </b> you'll also need to add it to
|
||||
* {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
|
||||
* @param refreshServiceOnPackageUpdate when {@code true}, the
|
||||
* {@link AbstractPerUserSystemService} is removed from the cache (and re-added) when the
|
||||
* service package is updated; when {@code false}, the service is untouched during the
|
||||
* update.
|
||||
* @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the
|
||||
* {@link AbstractPerUserSystemService} is removed from the cache when the service
|
||||
* package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the
|
||||
* {@link AbstractPerUserSystemService} is removed from the cache and immediately
|
||||
* re-added when the service package is updated; when
|
||||
* {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update.
|
||||
*/
|
||||
protected AbstractMasterSystemService(@NonNull Context context,
|
||||
@Nullable ServiceNameResolver serviceNameResolver,
|
||||
@Nullable String disallowProperty, boolean refreshServiceOnPackageUpdate) {
|
||||
@Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) {
|
||||
super(context);
|
||||
|
||||
mRefreshServiceOnPackageUpdate = refreshServiceOnPackageUpdate;
|
||||
mPackageUpdatePolicy = packageUpdatePolicy;
|
||||
|
||||
mServiceNameResolver = serviceNameResolver;
|
||||
if (mServiceNameResolver != null) {
|
||||
@@ -645,7 +677,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
final int size = mServicesCache.size();
|
||||
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
|
||||
pw.print(" Verbose: "); pw.println(realVerbose);
|
||||
pw.print("Refresh on package update: "); pw.println(mRefreshServiceOnPackageUpdate);
|
||||
pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy);
|
||||
if (mUpdatingPackageNames != null) {
|
||||
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
|
||||
}
|
||||
@@ -701,12 +733,21 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
}
|
||||
mUpdatingPackageNames.put(userId, packageName);
|
||||
onServicePackageUpdatingLocked(userId);
|
||||
if (mRefreshServiceOnPackageUpdate) {
|
||||
if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) {
|
||||
if (debug) {
|
||||
Slog.d(mTag, "Removing service for user " + userId + " because package "
|
||||
+ activePackageName + " is being updated");
|
||||
Slog.d(mTag, "Removing service for user " + userId
|
||||
+ " because package " + activePackageName
|
||||
+ " is being updated");
|
||||
}
|
||||
removeCachedServiceLocked(userId);
|
||||
|
||||
if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) {
|
||||
if (debug) {
|
||||
Slog.d(mTag, "Eagerly recreating service for user "
|
||||
+ userId);
|
||||
}
|
||||
getServiceForUserLocked(userId);
|
||||
}
|
||||
} else {
|
||||
if (debug) {
|
||||
Slog.d(mTag, "Holding service for user " + userId + " while package "
|
||||
|
||||
@@ -254,6 +254,8 @@ public final class SystemServer {
|
||||
"com.android.server.autofill.AutofillManagerService";
|
||||
private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
|
||||
"com.android.server.contentcapture.ContentCaptureManagerService";
|
||||
private static final String SYSTEM_CAPTIONS_MANAGER_SERVICE_CLASS =
|
||||
"com.android.server.systemcaptions.SystemCaptionsManagerService";
|
||||
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
|
||||
"com.android.server.timezone.RulesManagerService$Lifecycle";
|
||||
private static final String IOT_SERVICE_CLASS =
|
||||
@@ -1232,6 +1234,8 @@ public final class SystemServer {
|
||||
startContentCaptureService(context);
|
||||
startAttentionService(context);
|
||||
|
||||
startSystemCaptionsManagerService(context);
|
||||
|
||||
// App prediction manager service
|
||||
traceBeginAndSlog("StartAppPredictionService");
|
||||
mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
|
||||
@@ -2225,6 +2229,19 @@ public final class SystemServer {
|
||||
}, BOOT_TIMINGS_TRACE_LOG);
|
||||
}
|
||||
|
||||
private void startSystemCaptionsManagerService(@NonNull Context context) {
|
||||
String serviceName = context.getString(
|
||||
com.android.internal.R.string.config_defaultSystemCaptionsManagerService);
|
||||
if (TextUtils.isEmpty(serviceName)) {
|
||||
Slog.d(TAG, "SystemCaptionsManagerService disabled because resource is not overlaid");
|
||||
return;
|
||||
}
|
||||
|
||||
traceBeginAndSlog("StartSystemCaptionsManagerService");
|
||||
mSystemServiceManager.startService(SYSTEM_CAPTIONS_MANAGER_SERVICE_CLASS);
|
||||
traceEnd();
|
||||
}
|
||||
|
||||
private void startContentCaptureService(@NonNull Context context) {
|
||||
// First check if it was explicitly enabled by DeviceConfig
|
||||
boolean explicitlyEnabled = false;
|
||||
@@ -2273,7 +2290,7 @@ public final class SystemServer {
|
||||
traceEnd();
|
||||
}
|
||||
|
||||
static final void startSystemUi(Context context, WindowManagerService windowManager) {
|
||||
private static void startSystemUi(Context context, WindowManagerService windowManager) {
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName("com.android.systemui",
|
||||
"com.android.systemui.SystemUIService"));
|
||||
|
||||
5
services/systemcaptions/Android.bp
Normal file
5
services/systemcaptions/Android.bp
Normal file
@@ -0,0 +1,5 @@
|
||||
java_library_static {
|
||||
name: "services.systemcaptions",
|
||||
srcs: ["java/**/*.java"],
|
||||
libs: ["services.core"],
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.server.systemcaptions;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
/** Manages the connection to the remote system captions manager service. */
|
||||
final class RemoteSystemCaptionsManagerService {
|
||||
|
||||
private static final String TAG = RemoteSystemCaptionsManagerService.class.getSimpleName();
|
||||
|
||||
private static final String SERVICE_INTERFACE =
|
||||
"android.service.systemcaptions.SystemCaptionsManagerService";
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final Context mContext;
|
||||
private final Intent mIntent;
|
||||
private final ComponentName mComponentName;
|
||||
private final int mUserId;
|
||||
private final boolean mVerbose;
|
||||
private final Handler mHandler;
|
||||
|
||||
private final RemoteServiceConnection mServiceConnection = new RemoteServiceConnection();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable private IBinder mService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean mBinding = false;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean mDestroyed = false;
|
||||
|
||||
RemoteSystemCaptionsManagerService(
|
||||
Context context, ComponentName componentName, int userId, boolean verbose) {
|
||||
mContext = context;
|
||||
mComponentName = componentName;
|
||||
mUserId = userId;
|
||||
mVerbose = verbose;
|
||||
mIntent = new Intent(SERVICE_INTERFACE).setComponent(componentName);
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "initialize()");
|
||||
}
|
||||
ensureBound();
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "destroy()");
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mDestroyed) {
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "destroy(): Already destroyed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
mDestroyed = true;
|
||||
ensureUnboundLocked();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isDestroyed() {
|
||||
synchronized (mLock) {
|
||||
return mDestroyed;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureBound() {
|
||||
synchronized (mLock) {
|
||||
if (mService != null || mBinding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "ensureBound(): binding");
|
||||
}
|
||||
mBinding = true;
|
||||
|
||||
int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
|
||||
boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags,
|
||||
mHandler, new UserHandle(mUserId));
|
||||
if (!willBind) {
|
||||
Slog.w(TAG, "Could not bind to " + mIntent + " with flags " + flags);
|
||||
mBinding = false;
|
||||
mService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void ensureUnboundLocked() {
|
||||
if (mService == null && !mBinding) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBinding = false;
|
||||
mService = null;
|
||||
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "ensureUnbound(): unbinding");
|
||||
}
|
||||
mContext.unbindService(mServiceConnection);
|
||||
}
|
||||
|
||||
private class RemoteServiceConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
synchronized (mLock) {
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "onServiceConnected()");
|
||||
}
|
||||
if (mDestroyed || !mBinding) {
|
||||
Slog.wtf(TAG, "onServiceConnected() dispatched after unbindService");
|
||||
return;
|
||||
}
|
||||
mBinding = false;
|
||||
mService = service;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
synchronized (mLock) {
|
||||
if (mVerbose) {
|
||||
Slog.v(TAG, "onServiceDisconnected()");
|
||||
}
|
||||
mBinding = true;
|
||||
mService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.server.systemcaptions;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AppGlobals;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.infra.AbstractPerUserSystemService;
|
||||
|
||||
/** Manages the captions manager service on a per-user basis. */
|
||||
final class SystemCaptionsManagerPerUserService extends
|
||||
AbstractPerUserSystemService<SystemCaptionsManagerPerUserService,
|
||||
SystemCaptionsManagerService> {
|
||||
|
||||
private static final String TAG = SystemCaptionsManagerPerUserService.class.getSimpleName();
|
||||
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
private RemoteSystemCaptionsManagerService mRemoteService;
|
||||
|
||||
SystemCaptionsManagerPerUserService(
|
||||
@NonNull SystemCaptionsManagerService master,
|
||||
@NonNull Object lock, boolean disabled, @UserIdInt int userId) {
|
||||
super(master, lock, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected ServiceInfo newServiceInfoLocked(
|
||||
@SuppressWarnings("unused") @NonNull ComponentName serviceComponent)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
try {
|
||||
return AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
|
||||
PackageManager.GET_META_DATA, mUserId);
|
||||
} catch (RemoteException e) {
|
||||
throw new PackageManager.NameNotFoundException(
|
||||
"Could not get service for " + serviceComponent);
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void initializeLocked() {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "initialize()");
|
||||
}
|
||||
|
||||
RemoteSystemCaptionsManagerService service = getRemoteServiceLocked();
|
||||
if (service == null && mMaster.verbose) {
|
||||
Slog.v(TAG, "initialize(): Failed to init remote server");
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void destroyLocked() {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "destroyLocked()");
|
||||
}
|
||||
|
||||
if (mRemoteService != null) {
|
||||
mRemoteService.destroy();
|
||||
mRemoteService = null;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private RemoteSystemCaptionsManagerService getRemoteServiceLocked() {
|
||||
if (mRemoteService == null) {
|
||||
String serviceName = getComponentNameLocked();
|
||||
if (serviceName == null) {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "getRemoteServiceLocked(): Not set");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
|
||||
mRemoteService = new RemoteSystemCaptionsManagerService(
|
||||
getContext(),
|
||||
serviceComponent,
|
||||
mUserId,
|
||||
mMaster.verbose);
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "getRemoteServiceLocked(): initialize for user " + mUserId);
|
||||
}
|
||||
mRemoteService.initialize();
|
||||
}
|
||||
|
||||
return mRemoteService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.server.systemcaptions;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.server.infra.AbstractMasterSystemService;
|
||||
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
|
||||
|
||||
/** A system service to bind to a remote system captions manager service. */
|
||||
public final class SystemCaptionsManagerService extends
|
||||
AbstractMasterSystemService<SystemCaptionsManagerService,
|
||||
SystemCaptionsManagerPerUserService> {
|
||||
|
||||
public SystemCaptionsManagerService(@NonNull Context context) {
|
||||
super(context,
|
||||
new FrameworkResourcesServiceNameResolver(
|
||||
context,
|
||||
com.android.internal.R.string.config_defaultSystemCaptionsManagerService),
|
||||
/*disallowProperty=*/ null,
|
||||
/*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
// Do nothing. This service does not publish any local or system services.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SystemCaptionsManagerPerUserService newServiceLocked(
|
||||
@UserIdInt int resolvedUserId, boolean disabled) {
|
||||
SystemCaptionsManagerPerUserService perUserService =
|
||||
new SystemCaptionsManagerPerUserService(this, mLock, disabled, resolvedUserId);
|
||||
perUserService.initializeLocked();
|
||||
return perUserService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceRemoved(
|
||||
SystemCaptionsManagerPerUserService service, @UserIdInt int userId) {
|
||||
synchronized (mLock) {
|
||||
service.destroyLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user