1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ondevicepersonalization.services.process;
18 
19 import android.adservices.ondevicepersonalization.IsolatedService;
20 import android.adservices.ondevicepersonalization.aidl.IIsolatedService;
21 import android.adservices.ondevicepersonalization.aidl.IIsolatedServiceCallback;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.os.Bundle;
25 import android.os.RemoteException;
26 
27 
28 import com.android.ondevicepersonalization.internal.util.LoggerFactory;
29 import com.android.ondevicepersonalization.libraries.plugin.FailureType;
30 import com.android.ondevicepersonalization.libraries.plugin.Plugin;
31 import com.android.ondevicepersonalization.libraries.plugin.PluginCallback;
32 import com.android.ondevicepersonalization.libraries.plugin.PluginContext;
33 
34 /** Plugin that runs in an isolated process. */
35 public class OnDevicePersonalizationPlugin implements Plugin {
36     private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger();
37     private static final String TAG = "OnDevicePersonalizationPlugin";
38     private Bundle mInput;
39     private PluginCallback mPluginCallback;
40     private PluginContext mPluginContext;
41     private ClassLoader mClassLoader;
42 
43     @Override
setClassLoader(ClassLoader classLoader)44     public void setClassLoader(ClassLoader classLoader) {
45         mClassLoader = classLoader;
46     }
47 
48     @Override
onExecute( @onNull Bundle input, @NonNull PluginCallback callback, @Nullable PluginContext pluginContext)49     public void onExecute(
50             @NonNull Bundle input,
51             @NonNull PluginCallback callback,
52             @Nullable PluginContext pluginContext) {
53         sLogger.d(TAG + ": Executing plugin: " + input.toString());
54         mInput = input;
55         mPluginCallback = callback;
56         mPluginContext = pluginContext;
57 
58         try {
59             String className = input.getString(PluginProcessRunner.PARAM_CLASS_NAME_KEY);
60             if (className == null || className.isEmpty()) {
61                 sLogger.e(TAG + ": className missing.");
62                 sendErrorResult(FailureType.ERROR_EXECUTING_PLUGIN);
63                 return;
64             }
65 
66             int operation = input.getInt(PluginProcessRunner.PARAM_OPERATION_KEY);
67             if (operation == 0) {
68                 sLogger.e(TAG + ": operation missing or invalid.");
69                 sendErrorResult(FailureType.ERROR_EXECUTING_PLUGIN);
70                 return;
71             }
72 
73             Bundle serviceParams = input.getParcelable(PluginProcessRunner.PARAM_SERVICE_INPUT,
74                     Bundle.class);
75             if (serviceParams == null) {
76                 sLogger.e(TAG + ": Missing service input.");
77                 sendErrorResult(FailureType.ERROR_EXECUTING_PLUGIN);
78                 return;
79             }
80 
81             Class<?> clazz = Class.forName(className, true, mClassLoader);
82             IsolatedService service =
83                     (IsolatedService) clazz.getDeclaredConstructor().newInstance();
84             // TODO(b/249345663): Set the 'Context' for the service.
85             service.onCreate();
86             IIsolatedService binder =
87                     (IIsolatedService) service.onBind(null);
88 
89             binder.onRequest(operation, serviceParams,
90                     new IIsolatedServiceCallback.Stub() {
91                         @Override public void onSuccess(Bundle result) {
92                             try {
93                                 mPluginCallback.onSuccess(result);
94                             } catch (RemoteException e) {
95                                 sLogger.e(TAG + ": Callback error.", e);
96                             }
97                         }
98                         @Override public void onError(
99                                 int errorCode, int isolatedServiceErrorCode) {
100                             try {
101                                 mPluginCallback.onFailure(FailureType.ERROR_EXECUTING_PLUGIN);
102                             } catch (RemoteException e) {
103                                 sLogger.e(TAG + ": Callback error.", e);
104                             }
105                         }
106                     }
107             );
108 
109         } catch (Exception e) {
110             sLogger.e(TAG + ": Plugin failed. ", e);
111             sendErrorResult(FailureType.ERROR_EXECUTING_PLUGIN);
112         }
113     }
114 
sendErrorResult(FailureType failure)115     private void sendErrorResult(FailureType failure) {
116         try {
117             mPluginCallback.onFailure(failure);
118         } catch (RemoteException e) {
119             sLogger.e(TAG + ": Callback error.", e);
120         }
121     }
122 }
123