Merge "Add system captions manager service" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e29637d8dc
@@ -3558,6 +3558,12 @@
|
|||||||
-->
|
-->
|
||||||
<string name="config_defaultSystemCaptionsService" translatable="false"></string>
|
<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.
|
<!-- The package name for the incident report approver app.
|
||||||
This app is usually PermissionController or an app that replaces it. When
|
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
|
a bugreport or incident report with EXPLICT-level sharing flags is going to be
|
||||||
|
|||||||
@@ -3409,6 +3409,7 @@
|
|||||||
<java-symbol type="string" name="config_defaultContentSuggestionsService" />
|
<java-symbol type="string" name="config_defaultContentSuggestionsService" />
|
||||||
<java-symbol type="string" name="config_defaultAttentionService" />
|
<java-symbol type="string" name="config_defaultAttentionService" />
|
||||||
<java-symbol type="string" name="config_defaultSystemCaptionsService" />
|
<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="notification_channel_foreground_service" />
|
||||||
<java-symbol type="string" name="foreground_service_app_in_background" />
|
<java-symbol type="string" name="foreground_service_app_in_background" />
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ java_library {
|
|||||||
"services.print",
|
"services.print",
|
||||||
"services.restrictions",
|
"services.restrictions",
|
||||||
"services.startop",
|
"services.startop",
|
||||||
|
"services.systemcaptions",
|
||||||
"services.usage",
|
"services.usage",
|
||||||
"services.usb",
|
"services.usb",
|
||||||
"services.voiceinteraction",
|
"services.voiceinteraction",
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ public final class ContentCaptureManagerService extends
|
|||||||
public ContentCaptureManagerService(@NonNull Context context) {
|
public ContentCaptureManagerService(@NonNull Context context) {
|
||||||
super(context, new FrameworkResourcesServiceNameResolver(context,
|
super(context, new FrameworkResourcesServiceNameResolver(context,
|
||||||
com.android.internal.R.string.config_defaultContentCaptureService),
|
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,
|
DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
|
||||||
ActivityThread.currentApplication().getMainExecutor(),
|
ActivityThread.currentApplication().getMainExecutor(),
|
||||||
(namespace, key, value) -> onDeviceConfigChange(key, value));
|
(namespace, key, value) -> onDeviceConfigChange(key, value));
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.server.infra;
|
package com.android.server.infra;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.UserIdInt;
|
import android.annotation.UserIdInt;
|
||||||
@@ -45,6 +46,8 @@ import com.android.server.LocalServices;
|
|||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,6 +78,30 @@ import java.util.List;
|
|||||||
public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>,
|
public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>,
|
||||||
S extends AbstractPerUserSystemService<S, M>> extends SystemService {
|
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
|
* 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.
|
* 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.
|
* 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 ServiceNameResolver serviceNameResolver,
|
||||||
@Nullable String disallowProperty) {
|
@Nullable String disallowProperty) {
|
||||||
this(context, serviceNameResolver, 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
|
* @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
|
* disables the service. <b>NOTE: </b> you'll also need to add it to
|
||||||
* {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
|
* {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
|
||||||
* @param refreshServiceOnPackageUpdate when {@code true}, the
|
* @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the
|
||||||
* {@link AbstractPerUserSystemService} is removed from the cache (and re-added) when the
|
* {@link AbstractPerUserSystemService} is removed from the cache when the service
|
||||||
* service package is updated; when {@code false}, the service is untouched during the
|
* package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the
|
||||||
* update.
|
* {@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,
|
protected AbstractMasterSystemService(@NonNull Context context,
|
||||||
@Nullable ServiceNameResolver serviceNameResolver,
|
@Nullable ServiceNameResolver serviceNameResolver,
|
||||||
@Nullable String disallowProperty, boolean refreshServiceOnPackageUpdate) {
|
@Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
mRefreshServiceOnPackageUpdate = refreshServiceOnPackageUpdate;
|
mPackageUpdatePolicy = packageUpdatePolicy;
|
||||||
|
|
||||||
mServiceNameResolver = serviceNameResolver;
|
mServiceNameResolver = serviceNameResolver;
|
||||||
if (mServiceNameResolver != null) {
|
if (mServiceNameResolver != null) {
|
||||||
@@ -645,7 +677,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
|||||||
final int size = mServicesCache.size();
|
final int size = mServicesCache.size();
|
||||||
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
|
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
|
||||||
pw.print(" Verbose: "); pw.println(realVerbose);
|
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) {
|
if (mUpdatingPackageNames != null) {
|
||||||
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
|
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
|
||||||
}
|
}
|
||||||
@@ -701,12 +733,21 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
|||||||
}
|
}
|
||||||
mUpdatingPackageNames.put(userId, packageName);
|
mUpdatingPackageNames.put(userId, packageName);
|
||||||
onServicePackageUpdatingLocked(userId);
|
onServicePackageUpdatingLocked(userId);
|
||||||
if (mRefreshServiceOnPackageUpdate) {
|
if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
Slog.d(mTag, "Removing service for user " + userId + " because package "
|
Slog.d(mTag, "Removing service for user " + userId
|
||||||
+ activePackageName + " is being updated");
|
+ " because package " + activePackageName
|
||||||
|
+ " is being updated");
|
||||||
}
|
}
|
||||||
removeCachedServiceLocked(userId);
|
removeCachedServiceLocked(userId);
|
||||||
|
|
||||||
|
if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) {
|
||||||
|
if (debug) {
|
||||||
|
Slog.d(mTag, "Eagerly recreating service for user "
|
||||||
|
+ userId);
|
||||||
|
}
|
||||||
|
getServiceForUserLocked(userId);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
Slog.d(mTag, "Holding service for user " + userId + " while package "
|
Slog.d(mTag, "Holding service for user " + userId + " while package "
|
||||||
|
|||||||
@@ -254,6 +254,8 @@ public final class SystemServer {
|
|||||||
"com.android.server.autofill.AutofillManagerService";
|
"com.android.server.autofill.AutofillManagerService";
|
||||||
private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
|
private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
|
||||||
"com.android.server.contentcapture.ContentCaptureManagerService";
|
"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 =
|
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
|
||||||
"com.android.server.timezone.RulesManagerService$Lifecycle";
|
"com.android.server.timezone.RulesManagerService$Lifecycle";
|
||||||
private static final String IOT_SERVICE_CLASS =
|
private static final String IOT_SERVICE_CLASS =
|
||||||
@@ -1232,6 +1234,8 @@ public final class SystemServer {
|
|||||||
startContentCaptureService(context);
|
startContentCaptureService(context);
|
||||||
startAttentionService(context);
|
startAttentionService(context);
|
||||||
|
|
||||||
|
startSystemCaptionsManagerService(context);
|
||||||
|
|
||||||
// App prediction manager service
|
// App prediction manager service
|
||||||
traceBeginAndSlog("StartAppPredictionService");
|
traceBeginAndSlog("StartAppPredictionService");
|
||||||
mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
|
mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
|
||||||
@@ -2225,6 +2229,19 @@ public final class SystemServer {
|
|||||||
}, BOOT_TIMINGS_TRACE_LOG);
|
}, 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) {
|
private void startContentCaptureService(@NonNull Context context) {
|
||||||
// First check if it was explicitly enabled by DeviceConfig
|
// First check if it was explicitly enabled by DeviceConfig
|
||||||
boolean explicitlyEnabled = false;
|
boolean explicitlyEnabled = false;
|
||||||
@@ -2273,7 +2290,7 @@ public final class SystemServer {
|
|||||||
traceEnd();
|
traceEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final void startSystemUi(Context context, WindowManagerService windowManager) {
|
private static void startSystemUi(Context context, WindowManagerService windowManager) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setComponent(new ComponentName("com.android.systemui",
|
intent.setComponent(new ComponentName("com.android.systemui",
|
||||||
"com.android.systemui.SystemUIService"));
|
"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