• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 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 android.adservices.ondevicepersonalization;
18 
19 
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.adservices.ondevicepersonalization.aidl.IDataAccessService;
24 import android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback;
25 import android.adservices.ondevicepersonalization.aidl.IFederatedComputeCallback;
26 import android.adservices.ondevicepersonalization.aidl.IFederatedComputeService;
27 import android.adservices.ondevicepersonalization.aidl.IIsolatedModelService;
28 import android.adservices.ondevicepersonalization.aidl.IIsolatedModelServiceCallback;
29 import android.adservices.ondevicepersonalization.aidl.IIsolatedService;
30 import android.adservices.ondevicepersonalization.aidl.IIsolatedServiceCallback;
31 import android.content.Context;
32 import android.federatedcompute.common.TrainingOptions;
33 import android.net.Uri;
34 import android.os.Bundle;
35 import android.os.PersistableBundle;
36 import android.os.RemoteException;
37 
38 import androidx.test.core.app.ApplicationProvider;
39 import androidx.test.filters.SmallTest;
40 
41 import com.android.federatedcompute.internal.util.AbstractServiceBinder;
42 import com.android.ondevicepersonalization.internal.util.ByteArrayParceledSlice;
43 import com.android.ondevicepersonalization.internal.util.PersistableBundleUtils;
44 
45 import org.junit.After;
46 import org.junit.AfterClass;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.junit.runners.Parameterized;
51 
52 import java.util.Arrays;
53 import java.util.Collection;
54 import java.util.concurrent.CountDownLatch;
55 import java.util.concurrent.TimeUnit;
56 
57 @SmallTest
58 @RunWith(Parameterized.class)
59 public class IsolatedServiceExceptionSafetyTest {
60 
61     private final Context mContext = ApplicationProvider.getApplicationContext();
62 
63     private IIsolatedService mIsolatedService;
64     private static AbstractServiceBinder<IIsolatedService> sServiceBinder;
65     private int mCallbackErrorCode;
66     private int mIsolatedServiceErrorCode;
67     private byte[] mSerializedExceptionInfo;
68     private CountDownLatch mLatch;
69 
70     @Parameterized.Parameter(0)
71     public String operation;
72 
73     @Parameterized.Parameters
data()74     public static Collection<Object[]> data() {
75         return Arrays.asList(
76                 new Object[][] {
77                     {RuntimeException.class.getName()},
78                     {NullPointerException.class.getName()},
79                     {IllegalArgumentException.class.getName()}
80                 });
81     }
82 
83     @Before
setUp()84     public void setUp() throws Exception {
85         if (sServiceBinder == null) {
86             sServiceBinder =
87                     AbstractServiceBinder.getIsolatedServiceBinderByServiceName(
88                             mContext,
89                             "android.adservices.ondevicepersonalization."
90                                     + "IsolatedServiceExceptionSafetyTestImpl",
91                             mContext.getPackageName(),
92                             "testIsolatedProcess",
93                             0,
94                             IIsolatedService.Stub::asInterface);
95         }
96 
97         mIsolatedService = sServiceBinder.getService(Runnable::run);
98         mLatch = new CountDownLatch(1);
99     }
100 
101     @After
tearDown()102     public void tearDown() {
103         mIsolatedService = null;
104         mCallbackErrorCode = 0;
105     }
106 
107     @AfterClass
tearDownClass()108     public static void tearDownClass() {
109         sServiceBinder.unbindFromService();
110     }
111 
112     @Test
testOnRequestExceptions()113     public void testOnRequestExceptions() throws Exception {
114         PersistableBundle appParams = new PersistableBundle();
115         appParams.putString("ex", operation);
116         ExecuteInputParcel input =
117                 new ExecuteInputParcel.Builder()
118                         .setAppPackageName("com.testapp")
119                         .setSerializedAppParams(new ByteArrayParceledSlice(
120                                 PersistableBundleUtils.toByteArray(appParams)))
121                         .build();
122         Bundle params = new Bundle();
123         params.putParcelable(Constants.EXTRA_INPUT, input);
124         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
125         params.putBinder(
126                 Constants.EXTRA_FEDERATED_COMPUTE_SERVICE_BINDER,
127                 new TestFederatedComputeService());
128         params.putBinder(Constants.EXTRA_MODEL_SERVICE_BINDER, new TestIsolatedModelService());
129         mIsolatedService.onRequest(Constants.OP_EXECUTE, params, new TestServiceCallback());
130         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
131         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
132     }
133 
134     @Test
testOnDownloadExceptions()135     public void testOnDownloadExceptions() throws Exception {
136         DownloadInputParcel input =
137                 new DownloadInputParcel.Builder()
138                         .setDataAccessServiceBinder(new TestDataAccessService(operation))
139                         .build();
140         Bundle params = new Bundle();
141         params.putParcelable(Constants.EXTRA_INPUT, input);
142         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
143         params.putBinder(
144                 Constants.EXTRA_FEDERATED_COMPUTE_SERVICE_BINDER,
145                 new TestFederatedComputeService());
146         mIsolatedService.onRequest(Constants.OP_DOWNLOAD, params, new TestServiceCallback());
147         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
148         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
149     }
150 
151     @Test
testOnRender()152     public void testOnRender() throws Exception {
153         RenderInputParcel input =
154                 new RenderInputParcel.Builder()
155                         .setRenderingConfig(
156                                 new RenderingConfig.Builder().addKey(operation).build())
157                         .build();
158         Bundle params = new Bundle();
159         params.putParcelable(Constants.EXTRA_INPUT, input);
160         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
161         mIsolatedService.onRequest(Constants.OP_RENDER, params, new TestServiceCallback());
162         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
163         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
164     }
165 
166     @Test
testOnEvent()167     public void testOnEvent() throws Exception {
168         PersistableBundle appParams = new PersistableBundle();
169         appParams.putString("ex", operation);
170         Bundle params = new Bundle();
171         params.putParcelable(
172                 Constants.EXTRA_INPUT,
173                 new EventInputParcel.Builder().setParameters(appParams).build());
174         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
175         params.putBinder(Constants.EXTRA_MODEL_SERVICE_BINDER, new TestIsolatedModelService());
176         mIsolatedService.onRequest(Constants.OP_WEB_VIEW_EVENT, params, new TestServiceCallback());
177         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
178         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
179     }
180 
181     @Test
testOnTrainingExamples()182     public void testOnTrainingExamples() throws Exception {
183         TrainingExamplesInputParcel input =
184                 new TrainingExamplesInputParcel.Builder()
185                         .setPopulationName("")
186                         .setTaskName(operation)
187                         .setResumptionToken(new byte[] {0})
188                         .build();
189         Bundle params = new Bundle();
190         params.putParcelable(Constants.EXTRA_INPUT, input);
191         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
192         mIsolatedService.onRequest(
193                 Constants.OP_TRAINING_EXAMPLE, params, new TestServiceCallback());
194         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
195         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
196     }
197 
198     @Test
testOnWebTrigger()199     public void testOnWebTrigger() throws Exception {
200         WebTriggerInputParcel input =
201                 new WebTriggerInputParcel.Builder(
202                                 Uri.parse("http://desturl"), operation, new byte[] {1, 2, 3})
203                         .build();
204         Bundle params = new Bundle();
205         params.putParcelable(Constants.EXTRA_INPUT, input);
206         params.putBinder(Constants.EXTRA_DATA_ACCESS_SERVICE_BINDER, new TestDataAccessService());
207         params.putBinder(Constants.EXTRA_MODEL_SERVICE_BINDER, new TestIsolatedModelService());
208         mIsolatedService.onRequest(Constants.OP_WEB_TRIGGER, params, new TestServiceCallback());
209         assertTrue(mLatch.await(5000, TimeUnit.MILLISECONDS));
210         assertEquals(Constants.STATUS_INTERNAL_ERROR, mCallbackErrorCode);
211     }
212 
213     class TestServiceCallback extends IIsolatedServiceCallback.Stub {
214         @Override
onSuccess(Bundle result)215         public void onSuccess(Bundle result) {
216             mLatch.countDown();
217         }
218 
219         @Override
onError( int errorCode, int isolatedServiceErrorCode, byte[] serializedExceptionInfo)220         public void onError(
221                 int errorCode,
222                 int isolatedServiceErrorCode,
223                 byte[] serializedExceptionInfo) {
224             mCallbackErrorCode = errorCode;
225             mIsolatedServiceErrorCode = isolatedServiceErrorCode;
226             mSerializedExceptionInfo = serializedExceptionInfo;
227             mLatch.countDown();
228         }
229     }
230 
231     static class TestDataAccessService extends IDataAccessService.Stub {
232 
233         String mOp;
234 
TestDataAccessService(String operation)235         TestDataAccessService(String operation) {
236             this.mOp = operation;
237         }
238 
TestDataAccessService()239         TestDataAccessService() {
240             mOp = null;
241         }
242 
243         @Override
onRequest(int operation, Bundle params, IDataAccessServiceCallback callback)244         public void onRequest(int operation, Bundle params, IDataAccessServiceCallback callback) {
245             // pass parameters for onDownloadCompleted testing
246             if (mOp != null) {
247                 Bundle bndl = new Bundle();
248                 bndl.putParcelable(
249                         Constants.EXTRA_RESULT, new ByteArrayParceledSlice(mOp.getBytes()));
250                 try {
251                     callback.onSuccess(bndl);
252                 } catch (RemoteException e) {
253                     throw new RuntimeException(e);
254                 }
255             }
256         }
257 
258         @Override
logApiCallStats(int apiName, long latencyMillis, int responseCode)259         public void logApiCallStats(int apiName, long latencyMillis, int responseCode) {}
260     }
261 
262     static class TestFederatedComputeService extends IFederatedComputeService.Stub {
263         @Override
schedule(TrainingOptions trainingOptions, IFederatedComputeCallback callback)264         public void schedule(TrainingOptions trainingOptions, IFederatedComputeCallback callback) {}
265 
cancel(String populationName, IFederatedComputeCallback callback)266         public void cancel(String populationName, IFederatedComputeCallback callback) {}
267     }
268 
269     static class TestIsolatedModelService extends IIsolatedModelService.Stub {
270         @Override
runInference(Bundle params, IIsolatedModelServiceCallback callback)271         public void runInference(Bundle params, IIsolatedModelServiceCallback callback) {}
272     }
273 }
274