Server implementation of WallpaperEffectsService API.

Test: cts tests
Bug: 213238425
CTS-Coverage-Bug: 213238425
Change-Id: Id94764483b80a62a9fcaf8b2205b63e5cb66473c
This commit is contained in:
Sharon Su
2022-02-01 22:09:36 +00:00
parent 0b1dea8145
commit a5afd3736a
7 changed files with 691 additions and 1 deletions

View File

@@ -102,6 +102,7 @@ filegroup {
":services.usage-sources",
":services.usb-sources",
":services.voiceinteraction-sources",
":services.wallpapereffectsgeneration-sources",
":services.wifi-sources",
],
visibility: ["//visibility:private"],
@@ -158,6 +159,7 @@ java_library {
"services.usage",
"services.usb",
"services.voiceinteraction",
"services.wallpapereffectsgeneration",
"services.wifi",
"service-blobstore",
"service-jobscheduler",

View File

@@ -369,6 +369,8 @@ public final class SystemServer implements Dumpable {
"com.android.server.adb.AdbService$Lifecycle";
private static final String SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS =
"com.android.server.speech.SpeechRecognitionManagerService";
private static final String WALLPAPER_EFFECTS_GENERATION_MANAGER_SERVICE_CLASS =
"com.android.server.wallpapereffectsgeneration.WallpaperEffectsGenerationManagerService";
private static final String APP_PREDICTION_MANAGER_SERVICE_CLASS =
"com.android.server.appprediction.AppPredictionManagerService";
private static final String CONTENT_SUGGESTIONS_SERVICE_CLASS =
@@ -1891,7 +1893,6 @@ public final class SystemServer implements Dumpable {
}
t.traceEnd();
t.traceBegin("StartIpSecService");
try {
ipSecService = IpSecService.create(context);
@@ -2132,6 +2133,14 @@ public final class SystemServer implements Dumpable {
Slog.i(TAG, "Wallpaper service disabled by config");
}
// WallpaperEffectsGeneration manager service
// TODO (b/135218095): Use deviceHasConfigString(context,
// R.string.config_defaultWallpaperEffectsGenerationService)
t.traceBegin("StartWallpaperEffectsGenerationService");
mSystemServiceManager.startService(
WALLPAPER_EFFECTS_GENERATION_MANAGER_SERVICE_CLASS);
t.traceEnd();
t.traceBegin("StartAudioService");
if (!isArc) {
mSystemServiceManager.startService(AudioService.Lifecycle.class);

View File

@@ -0,0 +1,22 @@
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
}
filegroup {
name: "services.wallpapereffectsgeneration-sources",
srcs: ["java/**/*.java"],
path: "java",
visibility: ["//frameworks/base/services"],
}
java_library_static {
name: "services.wallpapereffectsgeneration",
defaults: ["platform_service_defaults"],
srcs: [":services.wallpapereffectsgeneration-sources"],
libs: ["services.core"],
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2022 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.wallpapereffectsgeneration;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
import android.service.wallpapereffectsgeneration.IWallpaperEffectsGenerationService;
import android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService;
import android.text.format.DateUtils;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
/**
* Proxy to the
* {@link android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService}
* implementation in another process.
*/
public class RemoteWallpaperEffectsGenerationService extends
AbstractMultiplePendingRequestsRemoteService<RemoteWallpaperEffectsGenerationService,
IWallpaperEffectsGenerationService> {
private static final String TAG =
RemoteWallpaperEffectsGenerationService.class.getSimpleName();
private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
private final RemoteWallpaperEffectsGenerationServiceCallback mCallback;
public RemoteWallpaperEffectsGenerationService(Context context,
ComponentName componentName, int userId,
RemoteWallpaperEffectsGenerationServiceCallback callback,
boolean bindInstantServiceAllowed,
boolean verbose) {
super(context, WallpaperEffectsGenerationService.SERVICE_INTERFACE,
componentName, userId, callback,
context.getMainThreadHandler(),
bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
verbose, /* initialCapacity= */ 1);
mCallback = callback;
}
@Override
protected IWallpaperEffectsGenerationService getServiceInterface(IBinder service) {
return IWallpaperEffectsGenerationService.Stub.asInterface(service);
}
@Override
protected long getTimeoutIdleBindMillis() {
return PERMANENT_BOUND_TIMEOUT_MS;
}
@Override
protected long getRemoteRequestMillis() {
return TIMEOUT_REMOTE_REQUEST_MILLIS;
}
/**
* Schedules a request to bind to the remote service.
*/
public void reconnect() {
super.scheduleBind();
}
/**
* Schedule async request on remote service.
*/
public void scheduleOnResolvedService(
@NonNull AsyncRequest<IWallpaperEffectsGenerationService> request) {
scheduleAsyncRequest(request);
}
/**
* Execute async request on remote service immediately instead of sending it to Handler queue.
*/
public void executeOnResolvedService(
@NonNull AsyncRequest<IWallpaperEffectsGenerationService> request) {
executeAsyncRequest(request);
}
/**
* Notifies server (WallpaperEffectsGenerationPerUserService) about unexpected events..
*/
public interface RemoteWallpaperEffectsGenerationServiceCallback
extends VultureCallback<RemoteWallpaperEffectsGenerationService> {
/**
* Notifies change in connected state of the remote service.
*/
void onConnectedStateChanged(boolean connected);
}
@Override // from AbstractRemoteService
protected void handleOnConnectedStateChanged(boolean connected) {
if (mCallback != null) {
mCallback.onConnectedStateChanged(connected);
}
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) 2022 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.wallpapereffectsgeneration;
import static android.Manifest.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.content.Context.WALLPAPER_EFFECTS_GENERATION_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.wallpapereffectsgeneration.CinematicEffectRequest;
import android.app.wallpapereffectsgeneration.CinematicEffectResponse;
import android.app.wallpapereffectsgeneration.ICinematicEffectListener;
import android.app.wallpapereffectsgeneration.IWallpaperEffectsGenerationManager;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.util.Slog;
import com.android.server.LocalServices;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.util.function.Consumer;
/**
* A service used to return wallpaper effect given a request.
*/
public class WallpaperEffectsGenerationManagerService extends
AbstractMasterSystemService<WallpaperEffectsGenerationManagerService,
WallpaperEffectsGenerationPerUserService> {
private static final String TAG =
WallpaperEffectsGenerationManagerService.class.getSimpleName();
private static final boolean DEBUG = false;
private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
public WallpaperEffectsGenerationManagerService(Context context) {
super(context,
new FrameworkResourcesServiceNameResolver(context,
com.android.internal.R.string.config_defaultWallpaperEffectsGenerationService),
null,
PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
@Override
protected WallpaperEffectsGenerationPerUserService newServiceLocked(int resolvedUserId,
boolean disabled) {
return new WallpaperEffectsGenerationPerUserService(this, mLock, resolvedUserId);
}
@Override
public void onStart() {
publishBinderService(WALLPAPER_EFFECTS_GENERATION_SERVICE,
new WallpaperEffectsGenerationManagerStub());
}
@Override
protected void enforceCallingPermissionForManagement() {
getContext().enforceCallingPermission(MANAGE_WALLPAPER_EFFECTS_GENERATION, TAG);
}
@Override // from AbstractMasterSystemService
protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
final WallpaperEffectsGenerationPerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.onPackageUpdatedLocked();
}
}
@Override // from AbstractMasterSystemService
protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
final WallpaperEffectsGenerationPerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.onPackageRestartedLocked();
}
}
@Override
protected int getMaximumTemporaryServiceDurationMs() {
return MAX_TEMP_SERVICE_DURATION_MS;
}
private class WallpaperEffectsGenerationManagerStub
extends IWallpaperEffectsGenerationManager.Stub {
@Override
public void generateCinematicEffect(@NonNull CinematicEffectRequest request,
@NonNull ICinematicEffectListener listener) {
if (!runForUserLocked("generateCinematicEffect", (service) ->
service.onGenerateCinematicEffectLocked(request, listener))) {
try {
listener.onCinematicEffectGenerated(
new CinematicEffectResponse.Builder(
CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_ERROR,
request.getTaskId()).build());
} catch (RemoteException e) {
if (DEBUG) {
Slog.d(TAG, "fail to invoke cinematic effect listener for task["
+ request.getTaskId() + "]");
}
}
}
}
@Override
public void returnCinematicEffectResponse(@NonNull CinematicEffectResponse response) {
runForUserLocked("returnCinematicResponse", (service) ->
service.onReturnCinematicEffectResponseLocked(response));
}
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) {
new WallpaperEffectsGenerationManagerServiceShellCommand(
WallpaperEffectsGenerationManagerService.this)
.exec(this, in, out, err, args, callback, resultReceiver);
}
/**
* Execute the operation for the user locked. Return true if
* WallpaperEffectsGenerationPerUserService is found for the user.
* Otherwise return false.
*/
private boolean runForUserLocked(@NonNull final String func,
@NonNull final Consumer<WallpaperEffectsGenerationPerUserService> c) {
ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
Binder.getCallingUserHandle().getIdentifier(), false, ALLOW_NON_FULL,
null, null);
if (DEBUG) {
Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
}
Context ctx = getContext();
if (!(ctx.checkCallingPermission(MANAGE_WALLPAPER_EFFECTS_GENERATION)
== PERMISSION_GRANTED
|| mServiceNameResolver.isTemporary(userId)
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
String msg = "Permission Denial: Cannot call " + func + " from pid="
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
final long origId = Binder.clearCallingIdentity();
boolean accepted = false;
try {
synchronized (mLock) {
final WallpaperEffectsGenerationPerUserService service =
getServiceForUserLocked(userId);
if (service != null) {
accepted = true;
c.accept(service);
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return accepted;
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2022 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.wallpapereffectsgeneration;
import android.annotation.NonNull;
import android.os.ShellCommand;
import java.io.PrintWriter;
/**
* The shell command implementation for the WallpaperEffectsGenerationService.
*/
public class WallpaperEffectsGenerationManagerServiceShellCommand extends ShellCommand {
private static final String TAG =
WallpaperEffectsGenerationManagerServiceShellCommand.class.getSimpleName();
private final WallpaperEffectsGenerationManagerService mService;
public WallpaperEffectsGenerationManagerServiceShellCommand(
@NonNull WallpaperEffectsGenerationManagerService service) {
mService = service;
}
@Override
public int onCommand(String cmd) {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
final PrintWriter pw = getOutPrintWriter();
switch (cmd) {
case "set": {
final String what = getNextArgRequired();
switch (what) {
case "temporary-service": {
final int userId = Integer.parseInt(getNextArgRequired());
String serviceName = getNextArg();
if (serviceName == null) {
mService.resetTemporaryService(userId);
pw.println("WallpaperEffectsGenerationService temporarily reset. ");
return 0;
}
final int duration = Integer.parseInt(getNextArgRequired());
mService.setTemporaryService(userId, serviceName, duration);
pw.println("WallpaperEffectsGenerationService temporarily set to "
+ serviceName + " for " + duration + "ms");
break;
}
}
}
break;
default:
return handleDefaultCommands(cmd);
}
return 0;
}
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter()) {
pw.println("WallpaperEffectsGenerationService commands:");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]");
pw.println(" Temporarily (for DURATION ms) changes the service implemtation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
}
}
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (C) 2022 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.wallpapereffectsgeneration;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.app.wallpapereffectsgeneration.CinematicEffectRequest;
import android.app.wallpapereffectsgeneration.CinematicEffectResponse;
import android.app.wallpapereffectsgeneration.ICinematicEffectListener;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
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;
/**
* Per-user instance of {@link WallpaperEffectsGenerationManagerService}.
*/
public class WallpaperEffectsGenerationPerUserService extends
AbstractPerUserSystemService<WallpaperEffectsGenerationPerUserService,
WallpaperEffectsGenerationManagerService> implements
RemoteWallpaperEffectsGenerationService.RemoteWallpaperEffectsGenerationServiceCallback {
private static final String TAG =
WallpaperEffectsGenerationPerUserService.class.getSimpleName();
@GuardedBy("mLock")
private CinematicEffectListenerWrapper mCinematicEffectListenerWrapper;
@Nullable
@GuardedBy("mLock")
private RemoteWallpaperEffectsGenerationService mRemoteService;
protected WallpaperEffectsGenerationPerUserService(
WallpaperEffectsGenerationManagerService master,
Object lock, int userId) {
super(master, lock, userId);
}
@Override // from PerUserSystemService
protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
throws NameNotFoundException {
ServiceInfo si;
try {
si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
PackageManager.GET_META_DATA, mUserId);
} catch (RemoteException e) {
throw new NameNotFoundException("Could not get service for " + serviceComponent);
}
if (!Manifest.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE.equals(si.permission)) {
Slog.w(TAG, "WallpaperEffectsGenerationService from '" + si.packageName
+ "' does not require permission "
+ Manifest.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE);
throw new SecurityException("Service does not require permission "
+ Manifest.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE);
}
return si;
}
@GuardedBy("mLock")
@Override // from PerUserSystemService
protected boolean updateLocked(boolean disabled) {
final boolean enabledChanged = super.updateLocked(disabled);
updateRemoteServiceLocked();
return enabledChanged;
}
/**
* Notifies the service of a new cinematic effect generation request.
*/
@GuardedBy("mLock")
public void onGenerateCinematicEffectLocked(
@NonNull CinematicEffectRequest cinematicEffectRequest,
@NonNull ICinematicEffectListener cinematicEffectListener) {
String newTaskId = cinematicEffectRequest.getTaskId();
// Previous request is still being processed.
if (mCinematicEffectListenerWrapper != null) {
if (mCinematicEffectListenerWrapper.mTaskId.equals(newTaskId)) {
invokeCinematicListenerAndCleanup(
new CinematicEffectResponse.Builder(
CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_PENDING, newTaskId)
.build()
);
} else {
invokeCinematicListenerAndCleanup(
new CinematicEffectResponse.Builder(
CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS,
newTaskId).build()
);
}
return;
}
RemoteWallpaperEffectsGenerationService remoteService = ensureRemoteServiceLocked();
if (remoteService != null) {
remoteService.executeOnResolvedService(
s -> s.onGenerateCinematicEffect(cinematicEffectRequest));
mCinematicEffectListenerWrapper =
new CinematicEffectListenerWrapper(newTaskId, cinematicEffectListener);
} else {
if (isDebug()) {
Slog.d(TAG, "Remote service not found");
}
try {
cinematicEffectListener.onCinematicEffectGenerated(
createErrorCinematicEffectResponse(newTaskId));
} catch (RemoteException e) {
if (isDebug()) {
Slog.d(TAG, "Failed to invoke cinematic effect listener for task [" + newTaskId
+ "]");
}
}
}
}
/**
* Notifies the service of a generated cinematic effect response.
*/
@GuardedBy("mLock")
public void onReturnCinematicEffectResponseLocked(
@NonNull CinematicEffectResponse cinematicEffectResponse) {
invokeCinematicListenerAndCleanup(cinematicEffectResponse);
}
@GuardedBy("mLock")
private void updateRemoteServiceLocked() {
if (mRemoteService != null) {
mRemoteService.destroy();
mRemoteService = null;
}
// End existing response and clean up listener for next request.
if (mCinematicEffectListenerWrapper != null) {
invokeCinematicListenerAndCleanup(
createErrorCinematicEffectResponse(mCinematicEffectListenerWrapper.mTaskId));
}
}
void onPackageUpdatedLocked() {
if (isDebug()) {
Slog.v(TAG, "onPackageUpdatedLocked()");
}
destroyAndRebindRemoteService();
}
void onPackageRestartedLocked() {
if (isDebug()) {
Slog.v(TAG, "onPackageRestartedLocked()");
}
destroyAndRebindRemoteService();
}
private void destroyAndRebindRemoteService() {
if (mRemoteService == null) {
return;
}
if (isDebug()) {
Slog.d(TAG, "Destroying the old remote service.");
}
mRemoteService.destroy();
mRemoteService = null;
mRemoteService = ensureRemoteServiceLocked();
if (mRemoteService != null) {
if (isDebug()) {
Slog.d(TAG, "Rebinding to the new remote service.");
}
mRemoteService.reconnect();
}
// Clean up listener for next request.
if (mCinematicEffectListenerWrapper != null) {
invokeCinematicListenerAndCleanup(
createErrorCinematicEffectResponse(mCinematicEffectListenerWrapper.mTaskId));
}
}
private CinematicEffectResponse createErrorCinematicEffectResponse(String taskId) {
return new CinematicEffectResponse.Builder(
CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_ERROR,
taskId).build();
}
@GuardedBy("mLock")
private void invokeCinematicListenerAndCleanup(
CinematicEffectResponse cinematicEffectResponse) {
try {
if (mCinematicEffectListenerWrapper != null
&& mCinematicEffectListenerWrapper.mListener != null) {
mCinematicEffectListenerWrapper.mListener.onCinematicEffectGenerated(
cinematicEffectResponse);
} else {
if (isDebug()) {
Slog.w(TAG, "Cinematic effect listener not found for task["
+ mCinematicEffectListenerWrapper.mTaskId + "]");
}
}
} catch (RemoteException e) {
if (isDebug()) {
Slog.w(TAG, "Error invoking cinematic effect listener for task["
+ mCinematicEffectListenerWrapper.mTaskId + "]");
}
} finally {
mCinematicEffectListenerWrapper = null;
}
}
@GuardedBy("mLock")
@Nullable
private RemoteWallpaperEffectsGenerationService ensureRemoteServiceLocked() {
if (mRemoteService == null) {
final String serviceName = getComponentNameLocked();
if (serviceName == null) {
if (mMaster.verbose) {
Slog.v(TAG, "ensureRemoteServiceLocked(): not set");
}
return null;
}
ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
mRemoteService = new RemoteWallpaperEffectsGenerationService(getContext(),
serviceComponent, mUserId, this,
mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
}
return mRemoteService;
}
@Override // from RemoteWallpaperEffectsGenerationService
public void onServiceDied(RemoteWallpaperEffectsGenerationService service) {
Slog.w(TAG, "remote wallpaper effects generation service died");
updateRemoteServiceLocked();
}
@Override // from RemoteWallpaperEffectsGenerationService
public void onConnectedStateChanged(boolean connected) {
if (!connected) {
Slog.w(TAG, "remote wallpaper effects generation service disconnected");
updateRemoteServiceLocked();
}
}
private static final class CinematicEffectListenerWrapper {
@NonNull
private final String mTaskId;
@NonNull
private final ICinematicEffectListener mListener;
CinematicEffectListenerWrapper(
@NonNull final String taskId,
@NonNull final ICinematicEffectListener listener) {
mTaskId = taskId;
mListener = listener;
}
}
}